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

wanghailin 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 97a1b00e48 [Improve][Connector-V2] RocketMQ Sink add message tag 
config (#7996)
97a1b00e48 is described below

commit 97a1b00e481d23314a9b498556653ab34d8764c7
Author: wengys <[email protected]>
AuthorDate: Wed Nov 13 18:46:59 2024 +0800

    [Improve][Connector-V2] RocketMQ Sink add message tag config (#7996)
---
 docs/en/connector-v2/sink/RocketMQ.md              |  1 +
 .../seatunnel/rocketmq/config/ProducerConfig.java  |  6 ++
 .../serialize/DefaultSeaTunnelRowSerializer.java   |  9 ++-
 .../seatunnel/rocketmq/sink/ProducerMetadata.java  |  2 +
 .../seatunnel/rocketmq/sink/RocketMqSink.java      |  3 +
 .../rocketmq/sink/RocketMqSinkWriter.java          |  1 +
 .../rocketmq/RocketMqConsumerMessage.java          | 30 ++++++++++
 .../e2e/connector/rocketmq/RocketMqIT.java         | 40 ++++++++++---
 ...rocketmq-sink_fake_to_rocketmq_message_tag.conf | 70 ++++++++++++++++++++++
 9 files changed, 154 insertions(+), 8 deletions(-)

diff --git a/docs/en/connector-v2/sink/RocketMQ.md 
b/docs/en/connector-v2/sink/RocketMQ.md
index f0672a3c7f..589aa49699 100644
--- a/docs/en/connector-v2/sink/RocketMQ.md
+++ b/docs/en/connector-v2/sink/RocketMQ.md
@@ -32,6 +32,7 @@ Write Rows to a Apache RocketMQ topic.
 | access.key           | String  | no       |                          | When 
ACL_ENABLED is true, access key cannot be empty                                 
                                                                               |
 | secret.key           | String  | no       |                          | When 
ACL_ENABLED is true, secret key cannot be empty                                 
                                                                               |
 | producer.group       | String  | no       | SeaTunnel-producer-Group | 
SeaTunnel-producer-Group                                                        
                                                                                
    |
+| tag                  | String  | no       | -                        | 
`RocketMQ` message tag.                                                         
                                                                                
    |
 | partition.key.fields | array   | no       | -                        | -     
                                                                                
                                                                              |
 | format               | String  | no       | json                     | Data 
format. The default format is json. Optional text format. The default field 
separator is ",".If you customize the delimiter, add the "field_delimiter" 
option. |
 | field.delimiter      | String  | no       | ,                        | 
Customize the field delimiter for data format.                                  
                                                                                
    |
diff --git 
a/seatunnel-connectors-v2/connector-rocketmq/src/main/java/org/apache/seatunnel/connectors/seatunnel/rocketmq/config/ProducerConfig.java
 
b/seatunnel-connectors-v2/connector-rocketmq/src/main/java/org/apache/seatunnel/connectors/seatunnel/rocketmq/config/ProducerConfig.java
index 134a9908fa..9b9b8d0b07 100644
--- 
a/seatunnel-connectors-v2/connector-rocketmq/src/main/java/org/apache/seatunnel/connectors/seatunnel/rocketmq/config/ProducerConfig.java
+++ 
b/seatunnel-connectors-v2/connector-rocketmq/src/main/java/org/apache/seatunnel/connectors/seatunnel/rocketmq/config/ProducerConfig.java
@@ -32,6 +32,12 @@ public class ProducerConfig extends Config {
                     .noDefaultValue()
                     .withDescription("RocketMq topic name. ");
 
+    public static final Option<String> TAG =
+            Options.key("tag")
+                    .stringType()
+                    .noDefaultValue()
+                    .withDescription("RocketMq message tag.");
+
     public static final Option<String> PRODUCER_GROUP =
             Options.key("producer.group")
                     .stringType()
diff --git 
a/seatunnel-connectors-v2/connector-rocketmq/src/main/java/org/apache/seatunnel/connectors/seatunnel/rocketmq/serialize/DefaultSeaTunnelRowSerializer.java
 
b/seatunnel-connectors-v2/connector-rocketmq/src/main/java/org/apache/seatunnel/connectors/seatunnel/rocketmq/serialize/DefaultSeaTunnelRowSerializer.java
index 558dfb96fc..b4d77fb76b 100644
--- 
a/seatunnel-connectors-v2/connector-rocketmq/src/main/java/org/apache/seatunnel/connectors/seatunnel/rocketmq/serialize/DefaultSeaTunnelRowSerializer.java
+++ 
b/seatunnel-connectors-v2/connector-rocketmq/src/main/java/org/apache/seatunnel/connectors/seatunnel/rocketmq/serialize/DefaultSeaTunnelRowSerializer.java
@@ -37,37 +37,44 @@ import java.util.function.Function;
 @Slf4j
 public class DefaultSeaTunnelRowSerializer implements 
SeaTunnelRowSerializer<byte[], byte[]> {
     private final String topic;
+    private final String tag;
     private final SerializationSchema keySerialization;
     private final SerializationSchema valueSerialization;
 
     public DefaultSeaTunnelRowSerializer(
             String topic,
+            String tag,
             SeaTunnelRowType seaTunnelRowType,
             SchemaFormat format,
             String delimiter) {
         this(
                 topic,
+                tag,
                 element -> null,
                 createSerializationSchema(seaTunnelRowType, format, 
delimiter));
     }
 
     public DefaultSeaTunnelRowSerializer(
             String topic,
+            String tag,
             List<String> keyFieldNames,
             SeaTunnelRowType seaTunnelRowType,
             SchemaFormat format,
             String delimiter) {
         this(
                 topic,
+                tag,
                 createKeySerializationSchema(keyFieldNames, seaTunnelRowType),
                 createSerializationSchema(seaTunnelRowType, format, 
delimiter));
     }
 
     public DefaultSeaTunnelRowSerializer(
             String topic,
+            String tag,
             SerializationSchema keySerialization,
             SerializationSchema valueSerialization) {
         this.topic = topic;
+        this.tag = tag;
         this.keySerialization = keySerialization;
         this.valueSerialization = valueSerialization;
     }
@@ -123,6 +130,6 @@ public class DefaultSeaTunnelRowSerializer implements 
SeaTunnelRowSerializer<byt
             return null;
         }
         byte[] key = keySerialization.serialize(row);
-        return new Message(topic, null, key == null ? null : new String(key), 
value);
+        return new Message(topic, tag, key == null ? null : new String(key), 
value);
     }
 }
diff --git 
a/seatunnel-connectors-v2/connector-rocketmq/src/main/java/org/apache/seatunnel/connectors/seatunnel/rocketmq/sink/ProducerMetadata.java
 
b/seatunnel-connectors-v2/connector-rocketmq/src/main/java/org/apache/seatunnel/connectors/seatunnel/rocketmq/sink/ProducerMetadata.java
index 34add2fd50..85c1433815 100644
--- 
a/seatunnel-connectors-v2/connector-rocketmq/src/main/java/org/apache/seatunnel/connectors/seatunnel/rocketmq/sink/ProducerMetadata.java
+++ 
b/seatunnel-connectors-v2/connector-rocketmq/src/main/java/org/apache/seatunnel/connectors/seatunnel/rocketmq/sink/ProducerMetadata.java
@@ -31,6 +31,8 @@ public class ProducerMetadata implements Serializable {
     private RocketMqBaseConfiguration configuration;
     /** send topic */
     private String topic;
+    /** message tag */
+    private String tag;
 
     /** partition key fields */
     private List<String> partitionKeyFields;
diff --git 
a/seatunnel-connectors-v2/connector-rocketmq/src/main/java/org/apache/seatunnel/connectors/seatunnel/rocketmq/sink/RocketMqSink.java
 
b/seatunnel-connectors-v2/connector-rocketmq/src/main/java/org/apache/seatunnel/connectors/seatunnel/rocketmq/sink/RocketMqSink.java
index 9fda05dece..2bd55150c0 100644
--- 
a/seatunnel-connectors-v2/connector-rocketmq/src/main/java/org/apache/seatunnel/connectors/seatunnel/rocketmq/sink/RocketMqSink.java
+++ 
b/seatunnel-connectors-v2/connector-rocketmq/src/main/java/org/apache/seatunnel/connectors/seatunnel/rocketmq/sink/RocketMqSink.java
@@ -74,6 +74,9 @@ public class RocketMqSink extends 
AbstractSimpleSink<SeaTunnelRow, Void> {
         }
         producerMetadata = new ProducerMetadata();
         
producerMetadata.setTopic(config.getString(ProducerConfig.TOPIC.key()));
+        if (config.hasPath(ProducerConfig.TAG.key())) {
+            
producerMetadata.setTag(config.getString(ProducerConfig.TAG.key()));
+        }
         RocketMqBaseConfiguration.Builder baseConfigurationBuilder =
                 RocketMqBaseConfiguration.newBuilder()
                         .producer()
diff --git 
a/seatunnel-connectors-v2/connector-rocketmq/src/main/java/org/apache/seatunnel/connectors/seatunnel/rocketmq/sink/RocketMqSinkWriter.java
 
b/seatunnel-connectors-v2/connector-rocketmq/src/main/java/org/apache/seatunnel/connectors/seatunnel/rocketmq/sink/RocketMqSinkWriter.java
index b8cbaf70da..8e3bd4d1a0 100644
--- 
a/seatunnel-connectors-v2/connector-rocketmq/src/main/java/org/apache/seatunnel/connectors/seatunnel/rocketmq/sink/RocketMqSinkWriter.java
+++ 
b/seatunnel-connectors-v2/connector-rocketmq/src/main/java/org/apache/seatunnel/connectors/seatunnel/rocketmq/sink/RocketMqSinkWriter.java
@@ -78,6 +78,7 @@ public class RocketMqSinkWriter extends 
AbstractSinkWriter<SeaTunnelRow, Void> {
             SeaTunnelRowType seaTunnelRowType) {
         return new DefaultSeaTunnelRowSerializer(
                 producerMetadata.getTopic(),
+                producerMetadata.getTag(),
                 getPartitionKeyFields(seaTunnelRowType),
                 seaTunnelRowType,
                 producerMetadata.getFormat(),
diff --git 
a/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-rocketmq-e2e/src/test/java/org/apache/seatunnel/e2e/connector/rocketmq/RocketMqConsumerMessage.java
 
b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-rocketmq-e2e/src/test/java/org/apache/seatunnel/e2e/connector/rocketmq/RocketMqConsumerMessage.java
new file mode 100644
index 0000000000..594f193df1
--- /dev/null
+++ 
b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-rocketmq-e2e/src/test/java/org/apache/seatunnel/e2e/connector/rocketmq/RocketMqConsumerMessage.java
@@ -0,0 +1,30 @@
+/*
+ * 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.e2e.connector.rocketmq;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@AllArgsConstructor
+public class RocketMqConsumerMessage {
+    private String value;
+    private String tag;
+}
diff --git 
a/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-rocketmq-e2e/src/test/java/org/apache/seatunnel/e2e/connector/rocketmq/RocketMqIT.java
 
b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-rocketmq-e2e/src/test/java/org/apache/seatunnel/e2e/connector/rocketmq/RocketMqIT.java
index 01d7c77683..a07818476b 100644
--- 
a/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-rocketmq-e2e/src/test/java/org/apache/seatunnel/e2e/connector/rocketmq/RocketMqIT.java
+++ 
b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-rocketmq-e2e/src/test/java/org/apache/seatunnel/e2e/connector/rocketmq/RocketMqIT.java
@@ -147,6 +147,7 @@ public class RocketMqIT extends TestSuiteBase implements 
TestResource {
         DefaultSeaTunnelRowSerializer serializer =
                 new DefaultSeaTunnelRowSerializer(
                         "test_topic_source",
+                        null,
                         SEATUNNEL_ROW_TYPE,
                         DEFAULT_FORMAT,
                         DEFAULT_FIELD_DELIMITER);
@@ -183,7 +184,7 @@ public class RocketMqIT extends TestSuiteBase implements 
TestResource {
         Assertions.assertEquals(0, execResult.getExitCode(), 
execResult.getStderr());
 
         String topicName = "test_topic";
-        Map<String, String> data = getRocketMqConsumerData(topicName);
+        Map<String, RocketMqConsumerMessage> data = 
getRocketMqConsumerData(topicName);
         ObjectMapper objectMapper = new ObjectMapper();
         String key = data.keySet().iterator().next();
         ObjectNode objectNode = objectMapper.readValue(key, ObjectNode.class);
@@ -199,7 +200,7 @@ public class RocketMqIT extends TestSuiteBase implements 
TestResource {
                 
container.executeJob("/rocketmq-text-sink_fake_to_rocketmq.conf");
         Assertions.assertEquals(0, execResult.getExitCode(), 
execResult.getStderr());
         String topicName = "test_text_topic";
-        Map<String, String> data = getRocketMqConsumerData(topicName);
+        Map<String, RocketMqConsumerMessage> data = 
getRocketMqConsumerData(topicName);
         Assertions.assertEquals(10, data.size());
     }
 
@@ -209,6 +210,7 @@ public class RocketMqIT extends TestSuiteBase implements 
TestResource {
         DefaultSeaTunnelRowSerializer serializer =
                 new DefaultSeaTunnelRowSerializer(
                         "test_topic_text",
+                        null,
                         SEATUNNEL_ROW_TYPE,
                         SchemaFormat.TEXT,
                         DEFAULT_FIELD_DELIMITER);
@@ -228,6 +230,7 @@ public class RocketMqIT extends TestSuiteBase implements 
TestResource {
         DefaultSeaTunnelRowSerializer serializer =
                 new DefaultSeaTunnelRowSerializer(
                         "test_topic_text_offset_check",
+                        null,
                         SEATUNNEL_ROW_TYPE,
                         SchemaFormat.TEXT,
                         DEFAULT_FIELD_DELIMITER);
@@ -245,6 +248,7 @@ public class RocketMqIT extends TestSuiteBase implements 
TestResource {
         DefaultSeaTunnelRowSerializer serializer =
                 new DefaultSeaTunnelRowSerializer(
                         "test_topic_json",
+                        null,
                         SEATUNNEL_ROW_TYPE,
                         DEFAULT_FORMAT,
                         DEFAULT_FIELD_DELIMITER);
@@ -292,6 +296,7 @@ public class RocketMqIT extends TestSuiteBase implements 
TestResource {
         DefaultSeaTunnelRowSerializer serializer =
                 new DefaultSeaTunnelRowSerializer(
                         "test_topic_group",
+                        null,
                         SEATUNNEL_ROW_TYPE,
                         DEFAULT_FORMAT,
                         DEFAULT_FIELD_DELIMITER);
@@ -299,6 +304,25 @@ public class RocketMqIT extends TestSuiteBase implements 
TestResource {
         testRocketMqGroupOffsetsToConsole(container);
     }
 
+    @TestTemplate
+    public void testSinkRocketMqMessageTag(TestContainer container)
+            throws IOException, InterruptedException {
+        Container.ExecResult execResult =
+                
container.executeJob("/rocketmq-sink_fake_to_rocketmq_message_tag.conf");
+        Assertions.assertEquals(0, execResult.getExitCode(), 
execResult.getStderr());
+
+        String topicName = "test_topic_message_tag";
+        String tag = "test_tag";
+        Map<String, RocketMqConsumerMessage> data = 
getRocketMqConsumerData(topicName);
+        ObjectMapper objectMapper = new ObjectMapper();
+        String key = data.keySet().iterator().next();
+        ObjectNode objectNode = objectMapper.readValue(key, ObjectNode.class);
+        Assertions.assertTrue(objectNode.has("c_map"));
+        Assertions.assertTrue(objectNode.has("c_string"));
+        Assertions.assertEquals(10, data.size());
+        Assertions.assertEquals(tag, data.get(key).getTag());
+    }
+
     public void testRocketMqGroupOffsetsToConsole(TestContainer container)
             throws IOException, InterruptedException {
         Container.ExecResult execResult =
@@ -334,8 +358,8 @@ public class RocketMqIT extends TestSuiteBase implements 
TestResource {
         }
     }
 
-    private Map<String, String> getRocketMqConsumerData(String topicName) {
-        Map<String, String> data = new HashMap<>();
+    private Map<String, RocketMqConsumerMessage> 
getRocketMqConsumerData(String topicName) {
+        Map<String, RocketMqConsumerMessage> data = new HashMap<>();
         try {
             DefaultLitePullConsumer consumer =
                     
RocketMqAdminUtil.initDefaultLitePullConsumer(newConfiguration(), false);
@@ -373,9 +397,11 @@ public class RocketMqIT extends TestSuiteBase implements 
TestResource {
                     break;
                 }
                 for (MessageExt message : messages) {
-                    data.put(
-                            message.getKeys(),
-                            new String(message.getBody(), 
StandardCharsets.UTF_8));
+                    RocketMqConsumerMessage consumerMessage =
+                            new RocketMqConsumerMessage(
+                                    new String(message.getBody(), 
StandardCharsets.UTF_8),
+                                    message.getTags());
+                    data.put(message.getKeys(), consumerMessage);
                     consumer.getOffsetStore()
                             .updateConsumeOffsetToBroker(
                                     new MessageQueue(
diff --git 
a/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-rocketmq-e2e/src/test/resources/rocketmq-sink_fake_to_rocketmq_message_tag.conf
 
b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-rocketmq-e2e/src/test/resources/rocketmq-sink_fake_to_rocketmq_message_tag.conf
new file mode 100644
index 0000000000..0badca6bf7
--- /dev/null
+++ 
b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-rocketmq-e2e/src/test/resources/rocketmq-sink_fake_to_rocketmq_message_tag.conf
@@ -0,0 +1,70 @@
+#
+# 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.
+#
+
+env {
+  parallelism = 1
+  job.mode = "BATCH"
+
+  #spark config
+  spark.app.name = "SeaTunnel"
+  spark.executor.instances = 1
+  spark.executor.cores = 1
+  spark.executor.memory = "1g"
+  spark.master = local
+}
+
+source {
+  FakeSource {
+    row.num = 10
+    map.size = 10
+    array.size = 10
+    bytes.length = 10
+    string.length = 10
+    schema = {
+      fields {
+        c_map = "map<string, smallint>"
+        c_array = "array<int>"
+        c_string = string
+        c_boolean = boolean
+        c_tinyint = tinyint
+        c_smallint = smallint
+        c_int = int
+        c_bigint = bigint
+        c_float = float
+        c_double = double
+        c_decimal = "decimal(30, 8)"
+        c_null = "null"
+        c_bytes = bytes
+        c_date = date
+        c_timestamp = timestamp
+      }
+    }
+  }
+}
+
+transform {
+}
+
+sink {
+  Rocketmq {
+    name.srv.addr = "rocketmq-e2e:9876"
+    topic = "test_topic_message_tag"
+    partition.key.fields = ["c_map", "c_string"]
+    producer.send.sync = true
+    tag = "test_tag"
+  }
+}
\ No newline at end of file

Reply via email to