* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "FlinkKafkaInternalProducer.h"
FlinkKafkaInternalProducer::FlinkKafkaInternalProducer(RdKafka::Conf* properties, const std::string& transactionalId)
: transactionalId_(transactionalId),
inTransaction_(false),
closed_(false)
{
producer_ = RdKafka::Producer::create(properties, errstr);
if (!producer_) {
throw std::runtime_error("FAILED to create producer: " + errstr);
}
}
FlinkKafkaInternalProducer::~FlinkKafkaInternalProducer()
{
delete producer_;
}
RdKafka::Producer* FlinkKafkaInternalProducer::getKafkaProducer()
{
return this->producer_;
}
void FlinkKafkaInternalProducer::Flush()
{
producer_->flush(timeout_);
if (inTransaction_) {
FlushNewPartitions();
}
}
void FlinkKafkaInternalProducer::BeginTransaction()
{
RdKafka::Error* err = producer_->begin_transaction();
if (err) {
throw std::runtime_error("FAILED to begin transaction: " + err->str());
}
inTransaction_ = true;
}
void FlinkKafkaInternalProducer::AbortTransaction()
{
LOG("AbortTransaction " + transactionalId_);
if (!inTransaction_) {
throw std::runtime_error("Transaction was not started");
}
RdKafka::Error* err = producer_->abort_transaction(timeout_);
if (err) {
throw std::runtime_error("FAILED to abort transaction: " + err->str());
}
inTransaction_ = false;
}
void FlinkKafkaInternalProducer::CommitTransaction()
{
LOG("CommitTransaction " + transactionalId_);
if (!inTransaction_) {
throw std::runtime_error("Transaction was not started");
}
RdKafka::Error* err = producer_->commit_transaction(timeout_);
if (err) {
throw std::runtime_error("FAILED to Commit transaction: " + err->str());
}
inTransaction_ = false;
}
bool FlinkKafkaInternalProducer::IsInTransaction() const
{
return inTransaction_;
}
void FlinkKafkaInternalProducer::Close()
{
closed_ = true;
if (inTransaction_) {
producer_->poll(0);
} else {
producer_->poll(pollTimeout_);
}
}
void FlinkKafkaInternalProducer::Close(int timeout)
{
closed_ = true;
producer_->poll(timeout);
}
bool FlinkKafkaInternalProducer::IsClosed() const
{
return closed_;
}
const std::string& FlinkKafkaInternalProducer::getTransactionalId() const
{
return transactionalId_;
}
int32_t FlinkKafkaInternalProducer::getEpoch() const
{
return 0;
}
int64_t FlinkKafkaInternalProducer::getProducerId() const
{
return 0;
}
void FlinkKafkaInternalProducer::initTransactionId(const std::string& transactionalId)
{
if (transactionalId != transactionalId_) {
setTransactionId(transactionalId);
producer_->init_transactions(timeout_);
}
}
void FlinkKafkaInternalProducer::setTransactionId(const std::string& transactionalId)
{
if (transactionalId != transactionalId_) {
if (inTransaction_) {
throw std::runtime_error("Another transaction is still open.");
}
}
}
void FlinkKafkaInternalProducer::FlushNewPartitions()
{
}
void* FlinkKafkaInternalProducer::GetTransactionManager() const
{
return nullptr;
}
void FlinkKafkaInternalProducer::transitionTransactionManagerStateTo(const std::string& state)
{
}
RdKafka::Conf* FlinkKafkaInternalProducer::withTransactionalId(
RdKafka::Conf* properties, const std::string& transactionalId)
{
if (transactionalId.empty()) {
return properties;
}
std::string errStr;
properties->set("transactional.id", transactionalId, errStr);
return properties;
}
void FlinkKafkaInternalProducer::resumeTransaction(int64_t producerId, int32_t epoch)
{
if (inTransaction_) {
throw std::runtime_error("Already in transaction " + transactionalId_);
}
if (producerId < 0 || epoch < 0) {
throw std::runtime_error(
"Incorrect values for producerId " + std::to_string(producerId) + " and epoch " + std::to_string(epoch));
}
}
void* FlinkKafkaInternalProducer::createProducerIdAndEpoch(int64_t producerId, int32_t epoch)
{
return nullptr;
}