This is an automated email from the ASF dual-hosted git repository.

davidzollo pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/seatunnel.git


The following commit(s) were added to refs/heads/dev by this push:
     new 7001ed6a3b [Fix][Connector-V2][Kafka] Fixed:   inverted 
commit_on_checkpoint for… (#10320)
7001ed6a3b is described below

commit 7001ed6a3b696fb8b2022840e66d63c7e436c76c
Author: tomma <[email protected]>
AuthorDate: Sun Jul 19 09:51:18 2026 +0800

    [Fix][Connector-V2][Kafka] Fixed:   inverted commit_on_checkpoint for… 
(#10320)
    
    Co-authored-by: DanielLeens <[email protected]>
---
 docs/en/connectors/source/Kafka.md                 |  2 +-
 docs/zh/connectors/source/Kafka.md                 |  2 +-
 .../seatunnel/kafka/config/KafkaSourceOptions.java |  2 +-
 .../kafka/source/KafkaPartitionSplitReader.java    | 74 +++++++++++--------
 .../source/KafkaPartitionSplitReaderTest.java      | 86 ++++++++++++++++++++++
 5 files changed, 131 insertions(+), 35 deletions(-)

diff --git a/docs/en/connectors/source/Kafka.md 
b/docs/en/connectors/source/Kafka.md
index 28e23bfef9..7402b4e6c2 100644
--- a/docs/en/connectors/source/Kafka.md
+++ b/docs/en/connectors/source/Kafka.md
@@ -42,7 +42,7 @@ They can be downloaded via install-plugin.sh or from the 
Maven central repositor
 | bootstrap.servers                   | String                                 
                                    | Yes      | -                        | 
Comma separated list of Kafka brokers.                                          
                                                                                
                                                                                
                                                                                
                  [...]
 | pattern                             | Boolean                                
                                    | No       | false                    | If 
`pattern` is set to `true`,the regular expression for a pattern of topic names 
to read from. All topics in clients with names that match the specified regular 
expression will be subscribed by the consumer.                                  
                                                                                
                [...]
 | consumer.group                      | String                                 
                                    | No       | SeaTunnel-Consumer-Group | 
`Kafka consumer group id`, used to distinguish different consumer groups.       
                                                                                
                                                                                
                                                                                
                  [...]
-| commit_on_checkpoint                | Boolean                                
                                    | No       | true                     | If 
true the consumer's offset will be periodically committed in the background.    
                                                                                
                                                                                
                                                                                
               [...]
+| commit_on_checkpoint                | Boolean                                
                                    | No       | true                     | If 
true, consumer offsets are committed only after a SeaTunnel checkpoint 
completes, and Kafka auto commit is disabled. If false, checkpoint commits are 
disabled and Kafka auto commit is enabled.                                      
                                                                                
                         [...]
 | poll.timeout                        | Long                                   
                                    | No       | 10000                    | The 
interval(millis) for poll messages.                                             
                                                                                
                                                                                
                                                                                
              [...]
 | kafka.config                        | Map                                    
                                    | No       | -                        | In 
addition to the above necessary parameters that must be specified by the `Kafka 
consumer` client, users can also specify multiple `consumer` client 
non-mandatory parameters, covering [all consumer parameters specified in the 
official Kafka 
document](https://kafka.apache.org/documentation.html#consumerconfigs).         
               [...]
 | schema                              | Config                                 
                                    | No       | -                        | The 
structure of the data, including field names and field types. For more details, 
please refer to [Schema 
Feature](../../introduction/concepts/schema-feature.md).                        
                                                                                
                                                                      [...]
diff --git a/docs/zh/connectors/source/Kafka.md 
b/docs/zh/connectors/source/Kafka.md
index 89921afaa2..89dfd2da13 100644
--- a/docs/zh/connectors/source/Kafka.md
+++ b/docs/zh/connectors/source/Kafka.md
@@ -42,7 +42,7 @@ import ChangeLog from '../changelog/connector-kafka.md';
 | bootstrap.servers                   | String                              | 
是    | -                            | 逗号分隔的 Kafka brokers 列表。                   
                                                                                
                                                                                
                                                                                
                                     |
 | pattern                             | Boolean                             | 
否    | false                        | 如果 `pattern` 设置为 
`true`,则会使用指定的正则表达式匹配并订阅主题。                                                     
                                                                                
                                                                                
                                                              |
 | consumer.group                      | String                              | 
否    | SeaTunnel-Consumer-Group     | `Kafka 消费者组 ID`,用于区分不同的消费者组。              
                                                                                
                                                                                
                                                                                
                                     |
-| commit_on_checkpoint                | Boolean                             | 
否    | true                         | 如果为 true,消费者的偏移量将会定期在后台提交。                
                                                                                
                                                                                
                                                                                
                                     |
+| commit_on_checkpoint                | Boolean                             | 
否    | true                         | 如果为 true,仅在 SeaTunnel checkpoint 
完成后提交消费者偏移量,并禁用 Kafka 自动提交;如果为 false,则禁用 checkpoint 提交并启用 Kafka 自动提交。           
                                                                                
                                                                                
                                                                                
    |
 | poll.timeout                        | Long                                | 
否    | 10000                        | kafka主动拉取时间间隔(毫秒)。                        
                                                                                
                                                                                
                                                                                
                                     |
 | kafka.config                        | Map                                 | 
否    | -                            | 除了上述必要参数外,用户还可以指定多个非强制的消费者客户端参数,覆盖 [Kafka 
官方文档](https://kafka.apache.org/documentation.html#consumerconfigs) 中指定的所有消费者参数。 
                                                                                
                                                                                
                                     |
 | schema                              | Config                              | 
否    | -                            | 数据结构,包括字段名称和字段类型。更多详情请参考 [Schema 
特性](../../introduction/concepts/schema-feature.md)。                             
                                                                                
                                                                                
                                                                                
       |
diff --git 
a/seatunnel-connectors-v2/connector-kafka/src/main/java/org/apache/seatunnel/connectors/seatunnel/kafka/config/KafkaSourceOptions.java
 
b/seatunnel-connectors-v2/connector-kafka/src/main/java/org/apache/seatunnel/connectors/seatunnel/kafka/config/KafkaSourceOptions.java
index 9373290978..f89ee28cc6 100644
--- 
a/seatunnel-connectors-v2/connector-kafka/src/main/java/org/apache/seatunnel/connectors/seatunnel/kafka/config/KafkaSourceOptions.java
+++ 
b/seatunnel-connectors-v2/connector-kafka/src/main/java/org/apache/seatunnel/connectors/seatunnel/kafka/config/KafkaSourceOptions.java
@@ -55,7 +55,7 @@ public class KafkaSourceOptions extends KafkaBaseOptions {
                     .booleanType()
                     .defaultValue(true)
                     .withDescription(
-                            "If true the consumer's offset will be 
periodically committed in the background.");
+                            "If true, consumer offsets are committed only 
after a SeaTunnel checkpoint completes, and Kafka auto commit is disabled. If 
false, checkpoint commits are disabled and Kafka auto commit is enabled.");
 
     public static final Option<Boolean> DEBEZIUM_RECORD_INCLUDE_SCHEMA =
             Options.key("debezium_record_include_schema")
diff --git 
a/seatunnel-connectors-v2/connector-kafka/src/main/java/org/apache/seatunnel/connectors/seatunnel/kafka/source/KafkaPartitionSplitReader.java
 
b/seatunnel-connectors-v2/connector-kafka/src/main/java/org/apache/seatunnel/connectors/seatunnel/kafka/source/KafkaPartitionSplitReader.java
index 9609534090..a61fadc65a 100644
--- 
a/seatunnel-connectors-v2/connector-kafka/src/main/java/org/apache/seatunnel/connectors/seatunnel/kafka/source/KafkaPartitionSplitReader.java
+++ 
b/seatunnel-connectors-v2/connector-kafka/src/main/java/org/apache/seatunnel/connectors/seatunnel/kafka/source/KafkaPartitionSplitReader.java
@@ -307,43 +307,53 @@ public class KafkaPartitionSplitReader
         consumer.commitAsync(offsetsToCommit, offsetCommitCallback);
     }
 
+    /**
+     * Builds Kafka consumer properties for the source reader.
+     *
+     * <p>The source either relies on checkpoint-triggered commits or Kafka 
auto commit, but never
+     * both at the same time.
+     */
+    static Properties buildConsumerProperties(
+            KafkaSourceConfig kafkaSourceConfig, int subtaskId, String 
clientIdPrefix) {
+        Properties props = new Properties();
+        kafkaSourceConfig
+                .getProperties()
+                .forEach(
+                        (key, value) ->
+                                props.setProperty(String.valueOf(key), 
String.valueOf(value)));
+        props.setProperty(ConsumerConfig.GROUP_ID_CONFIG, 
kafkaSourceConfig.getConsumerGroup());
+        props.setProperty(
+                ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, 
kafkaSourceConfig.getBootstrap());
+        if (kafkaSourceConfig.getProperties().get("client.id") == null) {
+            props.setProperty(
+                    ConsumerConfig.CLIENT_ID_CONFIG, clientIdPrefix + 
"-consumer-" + subtaskId);
+        } else {
+            props.setProperty(
+                    ConsumerConfig.CLIENT_ID_CONFIG,
+                    
kafkaSourceConfig.getProperties().get("client.id").toString()
+                            + "-"
+                            + subtaskId);
+        }
+        props.setProperty(
+                ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,
+                ByteArrayDeserializer.class.getName());
+        props.setProperty(
+                ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,
+                ByteArrayDeserializer.class.getName());
+        props.setProperty(
+                ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG,
+                String.valueOf(!kafkaSourceConfig.isCommitOnCheckpoint()));
+        props.setProperty(ConsumerConfig.ALLOW_AUTO_CREATE_TOPICS_CONFIG, 
"false");
+        return props;
+    }
+
     private KafkaConsumer<byte[], byte[]> initConsumer(
             KafkaSourceConfig kafkaSourceConfig, int subtaskId) {
 
         try (TemporaryClassLoaderContext ignored =
                 
TemporaryClassLoaderContext.of(kafkaSourceConfig.getClass().getClassLoader())) {
-            Properties props = new Properties();
-            kafkaSourceConfig
-                    .getProperties()
-                    .forEach(
-                            (key, value) ->
-                                    props.setProperty(String.valueOf(key), 
String.valueOf(value)));
-            props.setProperty(ConsumerConfig.GROUP_ID_CONFIG, 
kafkaSourceConfig.getConsumerGroup());
-            props.setProperty(
-                    ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, 
kafkaSourceConfig.getBootstrap());
-            if (this.kafkaSourceConfig.getProperties().get("client.id") == 
null) {
-                props.setProperty(
-                        ConsumerConfig.CLIENT_ID_CONFIG,
-                        CLIENT_ID_PREFIX + "-consumer-" + subtaskId);
-            } else {
-                props.setProperty(
-                        ConsumerConfig.CLIENT_ID_CONFIG,
-                        
this.kafkaSourceConfig.getProperties().get("client.id").toString()
-                                + "-"
-                                + subtaskId);
-            }
-            props.setProperty(
-                    ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,
-                    ByteArrayDeserializer.class.getName());
-            props.setProperty(
-                    ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,
-                    ByteArrayDeserializer.class.getName());
-            props.setProperty(
-                    ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG,
-                    String.valueOf(kafkaSourceConfig.isCommitOnCheckpoint()));
-
-            // Disable auto create topics feature
-            props.setProperty(ConsumerConfig.ALLOW_AUTO_CREATE_TOPICS_CONFIG, 
"false");
+            Properties props =
+                    buildConsumerProperties(kafkaSourceConfig, subtaskId, 
CLIENT_ID_PREFIX);
             return new KafkaConsumer<>(props);
         }
     }
diff --git 
a/seatunnel-connectors-v2/connector-kafka/src/test/java/org/apache/seatunnel/connectors/seatunnel/kafka/source/KafkaPartitionSplitReaderTest.java
 
b/seatunnel-connectors-v2/connector-kafka/src/test/java/org/apache/seatunnel/connectors/seatunnel/kafka/source/KafkaPartitionSplitReaderTest.java
new file mode 100644
index 0000000000..e8d7890a6a
--- /dev/null
+++ 
b/seatunnel-connectors-v2/connector-kafka/src/test/java/org/apache/seatunnel/connectors/seatunnel/kafka/source/KafkaPartitionSplitReaderTest.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.seatunnel.connectors.seatunnel.kafka.source;
+
+import org.apache.seatunnel.api.configuration.ReadonlyConfig;
+
+import org.apache.kafka.clients.consumer.ConsumerConfig;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * Tests the Kafka source reader consumer property mapping.
+ *
+ * <p>This guards the offset commit contract between SeaTunnel checkpoint 
commits and Kafka auto
+ * commit.
+ */
+public class KafkaPartitionSplitReaderTest {
+
+    /** Verifies that checkpoint commits disable Kafka auto commit. */
+    @Test
+    void 
testBuildConsumerPropertiesDisablesAutoCommitWhenCheckpointCommitEnabled() {
+        KafkaSourceConfig kafkaSourceConfig = new 
KafkaSourceConfig(createConfig(true));
+
+        Properties properties =
+                KafkaPartitionSplitReader.buildConsumerProperties(
+                        kafkaSourceConfig, 1, "seatunnel-test");
+
+        Assertions.assertEquals(
+                "false", 
properties.getProperty(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG));
+    }
+
+    /** Verifies that Kafka auto commit stays enabled when checkpoint commits 
are disabled. */
+    @Test
+    void 
testBuildConsumerPropertiesEnablesAutoCommitWhenCheckpointCommitDisabled() {
+        KafkaSourceConfig kafkaSourceConfig = new 
KafkaSourceConfig(createConfig(false));
+
+        Properties properties =
+                KafkaPartitionSplitReader.buildConsumerProperties(
+                        kafkaSourceConfig, 2, "seatunnel-test");
+
+        Assertions.assertEquals(
+                "true", 
properties.getProperty(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG));
+    }
+
+    /** Creates the minimum Kafka source config used by the tests. */
+    private ReadonlyConfig createConfig(boolean commitOnCheckpoint) {
+        Map<String, Object> configMap = new HashMap<>();
+        configMap.put("bootstrap.servers", "localhost:9092");
+        configMap.put("group.id", "test-group");
+        configMap.put("topic", "test-topic");
+        configMap.put("schema", createSchema());
+        configMap.put("format", "text");
+        configMap.put("commit_on_checkpoint", commitOnCheckpoint);
+        return ReadonlyConfig.fromMap(configMap);
+    }
+
+    /** Creates a minimal text schema for constructing {@link 
KafkaSourceConfig}. */
+    private Map<String, Object> createSchema() {
+        Map<String, Object> schemaFields = new HashMap<>();
+        schemaFields.put("id", "int");
+
+        Map<String, Object> schema = new HashMap<>();
+        schema.put("fields", schemaFields);
+        return schema;
+    }
+}

Reply via email to