This is an automated email from the ASF dual-hosted git repository.
lzljs3620320 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-paimon.git
The following commit(s) were added to refs/heads/master by this push:
new f68743c1b [CDC] Refactor cdc to reduce redundant code and set default
checkpoint interval (#2461)
f68743c1b is described below
commit f68743c1bf429db4b28fccd3e24e23bf0a5266f6
Author: yuzelin <[email protected]>
AuthorDate: Mon Dec 11 17:05:11 2023 +0800
[CDC] Refactor cdc to reduce redundant code and set default checkpoint
interval (#2461)
---
docs/content/cdc-ingestion/overview.md | 9 +-
.../flink/action/cdc/CdcActionCommonUtils.java | 13 ++
.../flink/action/cdc/MessageQueueSchemaUtils.java | 12 +-
.../cdc/MessageQueueSyncDatabaseActionBase.java | 81 --------
.../cdc/MessageQueueSyncTableActionBase.java | 28 +--
.../flink/action/cdc/SyncDatabaseActionBase.java | 113 +++--------
.../paimon/flink/action/cdc/SyncJobHandler.java | 222 +++++++++++++++++++++
.../flink/action/cdc/SyncTableActionBase.java | 155 ++++----------
.../action/cdc/SynchronizationActionBase.java | 154 ++++++++++++++
.../flink/action/cdc/kafka/KafkaActionUtils.java | 42 ++--
.../action/cdc/kafka/KafkaSyncDatabaseAction.java | 34 +---
.../cdc/kafka/KafkaSyncDatabaseActionFactory.java | 6 +-
.../action/cdc/kafka/KafkaSyncTableAction.java | 44 +---
.../action/cdc/mongodb/MongoDBActionUtils.java | 16 --
.../action/cdc/mongodb/MongoDBRecordParser.java | 5 -
.../cdc/mongodb/MongoDBSyncDatabaseAction.java | 44 +---
.../mongodb/MongoDBSyncDatabaseActionFactory.java | 6 +-
.../action/cdc/mongodb/MongoDBSyncTableAction.java | 48 ++---
.../flink/action/cdc/mysql/MySqlActionUtils.java | 25 ---
.../flink/action/cdc/mysql/MySqlRecordParser.java | 8 -
.../action/cdc/mysql/MySqlSyncDatabaseAction.java | 54 ++---
.../action/cdc/mysql/MySqlSyncTableAction.java | 45 ++---
.../flink/action/cdc/pulsar/PulsarActionUtils.java | 110 +++++-----
.../cdc/pulsar/PulsarSyncDatabaseAction.java | 34 +---
.../pulsar/PulsarSyncDatabaseActionFactory.java | 6 +-
.../action/cdc/pulsar/PulsarSyncTableAction.java | 48 +----
.../kafka/KafkaCanalSyncDatabaseActionITCase.java | 2 +-
.../KafkaMaxwellSyncDatabaseActionITCase.java | 2 +-
.../kafka/KafkaOggSyncDatabaseActionITCase.java | 2 +-
.../flink/action/cdc/kafka/KafkaSchemaITCase.java | 3 +-
.../cdc/mysql/MySqlSyncDatabaseActionITCase.java | 4 +-
.../cdc/mysql/MySqlSyncTableActionITCase.java | 38 ++++
.../action/cdc/pulsar/PulsarSchemaITCase.java | 3 +-
.../src/test/resources/mysql/sync_table_setup.sql | 13 ++
34 files changed, 674 insertions(+), 755 deletions(-)
diff --git a/docs/content/cdc-ingestion/overview.md
b/docs/content/cdc-ingestion/overview.md
index 031390104..d0de032f0 100644
--- a/docs/content/cdc-ingestion/overview.md
+++ b/docs/content/cdc-ingestion/overview.md
@@ -99,6 +99,13 @@ store up to 19 digits integer value. So you should ensure
the overflow won't occ
9. MySQL BINARY will be mapped to Paimon VARBINARY. This is because the binary
value is passed as bytes in binlog, so it
should be mapped to byte type (BYTES or VARBINARY). We choose VARBINARY
because it can retain the length information.
-## Setting Custom Job Name
+## Custom Job Settings
+
+### Checkpointing
+
+Use `-Dexecution.checkpointing.interval=<interval>` to enable checkpointing
and set interval. For 0.7 and later versions,
+if you haven't enabled checkpointing, Paimon will enable checkpointing by
default and set checkpoint interval to 180 seconds.
+
+### Job Name
Use `-Dpipeline.name=<job-name>` to set custom synchronization job name.
\ No newline at end of file
diff --git
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/CdcActionCommonUtils.java
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/CdcActionCommonUtils.java
index 97d4c9a10..d54b1ea36 100644
---
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/CdcActionCommonUtils.java
+++
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/CdcActionCommonUtils.java
@@ -26,6 +26,8 @@ import org.apache.paimon.schema.TableSchema;
import org.apache.paimon.types.DataField;
import org.apache.paimon.types.DataType;
+import org.apache.flink.configuration.ConfigOption;
+import org.apache.flink.configuration.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -283,4 +285,15 @@ public class CdcActionCommonUtils {
excludingPattern = "?!" + excludingPattern;
return String.format("(%s)(%s)", excludingPattern, includingPattern);
}
+
+ public static void checkRequiredOptions(
+ Configuration config, String confName, ConfigOption<?>...
configOptions) {
+ for (ConfigOption<?> configOption : configOptions) {
+ checkArgument(
+ config.contains(configOption),
+ "%s [%s] must be specified.",
+ confName,
+ configOption.key());
+ }
+ }
}
diff --git
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/MessageQueueSchemaUtils.java
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/MessageQueueSchemaUtils.java
index dc06a5a8c..326c73cca 100644
---
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/MessageQueueSchemaUtils.java
+++
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/MessageQueueSchemaUtils.java
@@ -38,14 +38,13 @@ public class MessageQueueSchemaUtils {
* Retrieves the Kafka schema for a given topic.
*
* @param consumer The wrapper of message queue consumer to fetch messages.
- * @param topic The topic to retrieve the schema for.
* @param dataFormat The data format for the messages in the message queue.
* @param typeMapping Data type mapping options.
* @return The schema for the topic.
* @throws SchemaRetrievalException If unable to retrieve the schema after
max retries.
*/
public static Schema getSchema(
- ConsumerWrapper consumer, String topic, DataFormat dataFormat,
TypeMapping typeMapping)
+ ConsumerWrapper consumer, DataFormat dataFormat, TypeMapping
typeMapping)
throws SchemaRetrievalException {
int retry = 0;
int retryInterval = 1000;
@@ -55,7 +54,7 @@ public class MessageQueueSchemaUtils {
while (true) {
Optional<Schema> schema =
- consumer.getRecords(topic, POLL_TIMEOUT_MILLIS).stream()
+ consumer.getRecords(POLL_TIMEOUT_MILLIS).stream()
.map(recordParser::buildSchema)
.filter(Objects::nonNull)
.findFirst();
@@ -66,7 +65,8 @@ public class MessageQueueSchemaUtils {
if (retry >= MAX_RETRY) {
throw new SchemaRetrievalException(
- String.format("Could not get metadata from server,
topic: %s", topic));
+ String.format(
+ "Could not get metadata from server, topic:
%s", consumer.topic()));
}
sleepSafely(retryInterval);
@@ -86,6 +86,8 @@ public class MessageQueueSchemaUtils {
/** Wrap the consumer for different message queues. */
public interface ConsumerWrapper extends AutoCloseable {
- List<String> getRecords(String topic, int pollTimeOutMills);
+ List<String> getRecords(int pollTimeOutMills);
+
+ String topic();
}
}
diff --git
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/MessageQueueSyncDatabaseActionBase.java
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/MessageQueueSyncDatabaseActionBase.java
deleted file mode 100644
index cc869a85b..000000000
---
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/MessageQueueSyncDatabaseActionBase.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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.paimon.flink.action.cdc;
-
-import org.apache.paimon.flink.action.Action;
-import org.apache.paimon.flink.action.MultiTablesSinkMode;
-import org.apache.paimon.flink.action.cdc.format.DataFormat;
-import org.apache.paimon.flink.sink.cdc.RichCdcMultiplexRecord;
-
-import org.apache.flink.api.common.functions.FlatMapFunction;
-
-import java.util.Collections;
-import java.util.Map;
-
-/**
- * An {@link Action} which synchronize the Multiple message queue topics into
one Paimon database.
- *
- * <p>For each message queue topic's table to be synchronized, if the
corresponding Paimon table
- * does not exist, this action will automatically create the table, and its
schema will be derived
- * from all specified message queue topic's tables. If the Paimon table
already exists and its
- * schema is different from that parsed from message queue record, this action
will try to preform
- * schema evolution.
- *
- * <p>This action supports a limited number of schema changes. Currently, the
framework can not drop
- * columns, so the behaviors of `DROP` will be ignored, `RENAME` will add a
new column. Currently
- * supported schema changes includes:
- *
- * <ul>
- * <li>Adding columns.
- * <li>Altering column types. More specifically,
- * <ul>
- * <li>altering from a string type (char, varchar, text) to another
string type with longer
- * length,
- * <li>altering from a binary type (binary, varbinary, blob) to
another binary type with
- * longer length,
- * <li>altering from an integer type (tinyint, smallint, int, bigint)
to another integer
- * type with wider range,
- * <li>altering from a floating-point type (float, double) to another
floating-point type
- * with wider range,
- * </ul>
- * are supported.
- * </ul>
- *
- * <p>To automatically synchronize new table, This action creates a single
sink for all Paimon
- * tables to be written. See {@link MultiTablesSinkMode#COMBINED}.
- */
-public abstract class MessageQueueSyncDatabaseActionBase extends
SyncDatabaseActionBase {
-
- public MessageQueueSyncDatabaseActionBase(
- String warehouse,
- String database,
- Map<String, String> catalogConfig,
- Map<String, String> mqConfig) {
- super(warehouse, database, catalogConfig, mqConfig);
- }
-
- protected abstract DataFormat getDataFormat();
-
- @Override
- protected FlatMapFunction<String, RichCdcMultiplexRecord> recordParse() {
- DataFormat format = getDataFormat();
- boolean caseSensitive = catalog.caseSensitive();
- return format.createParser(caseSensitive, typeMapping,
Collections.emptyList());
- }
-}
diff --git
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/MessageQueueSyncTableActionBase.java
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/MessageQueueSyncTableActionBase.java
index a0a976a8b..c3c6d49ff 100644
---
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/MessageQueueSyncTableActionBase.java
+++
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/MessageQueueSyncTableActionBase.java
@@ -19,12 +19,8 @@
package org.apache.paimon.flink.action.cdc;
import org.apache.paimon.flink.action.Action;
-import org.apache.paimon.flink.action.cdc.format.DataFormat;
-import org.apache.paimon.flink.sink.cdc.RichCdcMultiplexRecord;
import org.apache.paimon.schema.Schema;
-import org.apache.flink.api.common.functions.FlatMapFunction;
-
import java.util.Map;
/**
@@ -60,15 +56,16 @@ public abstract class MessageQueueSyncTableActionBase
extends SyncTableActionBas
String database,
String table,
Map<String, String> catalogConfig,
- Map<String, String> mqConfig) {
- super(warehouse, database, table, catalogConfig, mqConfig);
+ Map<String, String> mqConfig,
+ SyncJobHandler.SourceType sourceType) {
+ super(warehouse, database, table, catalogConfig, mqConfig, sourceType);
}
@Override
protected Schema retrieveSchema() throws Exception {
- String topic = topic();
- try (MessageQueueSchemaUtils.ConsumerWrapper consumer =
consumer(topic)) {
- return MessageQueueSchemaUtils.getSchema(consumer, topic,
getDataFormat(), typeMapping);
+ try (MessageQueueSchemaUtils.ConsumerWrapper consumer =
syncJobHandler.provideConsumer()) {
+ return MessageQueueSchemaUtils.getSchema(
+ consumer, syncJobHandler.provideDataFormat(), typeMapping);
}
}
@@ -83,17 +80,4 @@ public abstract class MessageQueueSyncTableActionBase
extends SyncTableActionBas
metadataConverters,
false);
}
-
- @Override
- protected FlatMapFunction<String, RichCdcMultiplexRecord> recordParse() {
- boolean caseSensitive = catalog.caseSensitive();
- DataFormat format = getDataFormat();
- return format.createParser(caseSensitive, typeMapping,
computedColumns);
- }
-
- protected abstract String topic();
-
- protected abstract MessageQueueSchemaUtils.ConsumerWrapper consumer(String
topic);
-
- protected abstract DataFormat getDataFormat();
}
diff --git
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/SyncDatabaseActionBase.java
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/SyncDatabaseActionBase.java
index d31c6cc12..74c2f6fc7 100644
---
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/SyncDatabaseActionBase.java
+++
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/SyncDatabaseActionBase.java
@@ -18,10 +18,8 @@
package org.apache.paimon.flink.action.cdc;
-import org.apache.paimon.annotation.VisibleForTesting;
import org.apache.paimon.catalog.AbstractCatalog;
import org.apache.paimon.flink.action.Action;
-import org.apache.paimon.flink.action.ActionBase;
import org.apache.paimon.flink.action.MultiTablesSinkMode;
import org.apache.paimon.flink.sink.cdc.EventParser;
import org.apache.paimon.flink.sink.cdc.FlinkCdcSyncDatabaseSinkBuilder;
@@ -31,51 +29,41 @@ import
org.apache.paimon.flink.sink.cdc.RichCdcMultiplexRecordEventParser;
import org.apache.paimon.table.FileStoreTable;
import org.apache.flink.api.common.functions.FlatMapFunction;
-import org.apache.flink.configuration.Configuration;
import org.apache.flink.streaming.api.datastream.DataStream;
-import org.apache.flink.streaming.api.datastream.DataStreamSource;
import javax.annotation.Nullable;
import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
-import java.util.Optional;
import java.util.regex.Pattern;
import static org.apache.paimon.flink.action.MultiTablesSinkMode.COMBINED;
/** Base {@link Action} for synchronizing into one Paimon database. */
-public abstract class SyncDatabaseActionBase extends ActionBase {
+public abstract class SyncDatabaseActionBase extends SynchronizationActionBase
{
- protected final String database;
- protected final Configuration cdcSourceConfig;
- protected Map<String, String> tableConfig = new HashMap<>();
protected boolean mergeShards = true;
protected MultiTablesSinkMode mode = COMBINED;
protected String tablePrefix = "";
protected String tableSuffix = "";
protected String includingTables = ".*";
@Nullable protected String excludingTables;
- protected TypeMapping typeMapping = TypeMapping.defaultMapping();
-
- protected CdcMetadataConverter[] metadataConverters = new
CdcMetadataConverter[] {};
protected List<FileStoreTable> tables = new ArrayList<>();
public SyncDatabaseActionBase(
String warehouse,
String database,
Map<String, String> catalogConfig,
- Map<String, String> cdcSourceConfig) {
- super(warehouse, catalogConfig);
- this.database = database;
- this.cdcSourceConfig = Configuration.fromMap(cdcSourceConfig);
- }
-
- public SyncDatabaseActionBase withTableConfig(Map<String, String>
tableConfig) {
- this.tableConfig = tableConfig;
- return this;
+ Map<String, String> cdcSourceConfig,
+ SyncJobHandler.SourceType sourceType) {
+ super(
+ warehouse,
+ database,
+ catalogConfig,
+ cdcSourceConfig,
+ new SyncJobHandler(sourceType, cdcSourceConfig, database));
}
public SyncDatabaseActionBase mergeShards(boolean mergeShards) {
@@ -114,42 +102,21 @@ public abstract class SyncDatabaseActionBase extends
ActionBase {
return this;
}
- public SyncDatabaseActionBase withTypeMapping(TypeMapping typeMapping) {
- this.typeMapping = typeMapping;
- return this;
- }
-
- public SyncDatabaseActionBase withMetadataColumns(List<String>
metadataColumns) {
- this.metadataConverters =
- metadataColumns.stream()
- .map(this::metadataConverter)
- .filter(Optional::isPresent)
- .map(Optional::get)
- .toArray(CdcMetadataConverter[]::new);
- return this;
+ @Override
+ protected void validateCaseSensitivity() {
+ AbstractCatalog.validateCaseInsensitive(caseSensitive, "Database",
database);
+ AbstractCatalog.validateCaseInsensitive(caseSensitive, "Table prefix",
tablePrefix);
+ AbstractCatalog.validateCaseInsensitive(caseSensitive, "Table suffix",
tableSuffix);
}
- protected Optional<CdcMetadataConverter<?>> metadataConverter(String
column) {
- return Optional.empty();
+ @Override
+ protected FlatMapFunction<String, RichCdcMultiplexRecord> recordParse() {
+ return syncJobHandler.provideRecordParser(
+ caseSensitive, Collections.emptyList(), typeMapping,
metadataConverters);
}
- protected void checkCdcSourceArgument() {}
-
- protected abstract DataStreamSource<String> buildSource() throws Exception;
-
- protected abstract String sourceName();
-
- protected abstract FlatMapFunction<String, RichCdcMultiplexRecord>
recordParse();
-
@Override
- public void build() throws Exception {
- checkCdcSourceArgument();
- boolean caseSensitive = catalog.caseSensitive();
-
- validateCaseInsensitive(caseSensitive);
-
- catalog.createDatabase(database, true);
-
+ protected EventParser.Factory<RichCdcMultiplexRecord>
buildEventParserFactory() {
NewTableSchemaBuilder schemaBuilder = new
NewTableSchemaBuilder(tableConfig, caseSensitive);
Pattern includingPattern = Pattern.compile(includingTables);
Pattern excludingPattern =
@@ -157,16 +124,15 @@ public abstract class SyncDatabaseActionBase extends
ActionBase {
TableNameConverter tableNameConverter =
new TableNameConverter(caseSensitive, mergeShards,
tablePrefix, tableSuffix);
- DataStream<RichCdcMultiplexRecord> input =
- buildSource().flatMap(recordParse()).name("Parse");
- EventParser.Factory<RichCdcMultiplexRecord> parserFactory =
- () ->
- new RichCdcMultiplexRecordEventParser(
- schemaBuilder,
- includingPattern,
- excludingPattern,
- tableNameConverter);
+ return () ->
+ new RichCdcMultiplexRecordEventParser(
+ schemaBuilder, includingPattern, excludingPattern,
tableNameConverter);
+ }
+ @Override
+ protected void buildSink(
+ DataStream<RichCdcMultiplexRecord> input,
+ EventParser.Factory<RichCdcMultiplexRecord> parserFactory) {
new FlinkCdcSyncDatabaseSinkBuilder<RichCdcMultiplexRecord>()
.withInput(input)
.withParserFactory(parserFactory)
@@ -177,27 +143,4 @@ public abstract class SyncDatabaseActionBase extends
ActionBase {
.withTableOptions(tableConfig)
.build();
}
-
- protected void validateCaseInsensitive(boolean caseSensitive) {
- AbstractCatalog.validateCaseInsensitive(caseSensitive, "Database",
database);
- AbstractCatalog.validateCaseInsensitive(caseSensitive, "Table prefix",
tablePrefix);
- AbstractCatalog.validateCaseInsensitive(caseSensitive, "Table suffix",
tableSuffix);
- }
-
- @VisibleForTesting
- public Map<String, String> tableConfig() {
- return tableConfig;
- }
-
- // ------------------------------------------------------------------------
- // Flink run methods
- // ------------------------------------------------------------------------
-
- protected abstract String jobName();
-
- @Override
- public void run() throws Exception {
- build();
- execute(jobName());
- }
}
diff --git
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/SyncJobHandler.java
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/SyncJobHandler.java
new file mode 100644
index 000000000..e469723b1
--- /dev/null
+++
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/SyncJobHandler.java
@@ -0,0 +1,222 @@
+/*
+ * 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.paimon.flink.action.cdc;
+
+import org.apache.paimon.flink.action.cdc.format.DataFormat;
+import org.apache.paimon.flink.action.cdc.kafka.KafkaActionUtils;
+import org.apache.paimon.flink.action.cdc.mongodb.MongoDBRecordParser;
+import org.apache.paimon.flink.action.cdc.mysql.MySqlActionUtils;
+import org.apache.paimon.flink.action.cdc.mysql.MySqlRecordParser;
+import org.apache.paimon.flink.action.cdc.pulsar.PulsarActionUtils;
+import org.apache.paimon.flink.sink.cdc.RichCdcMultiplexRecord;
+
+import com.ververica.cdc.connectors.mongodb.source.config.MongoDBSourceOptions;
+import com.ververica.cdc.connectors.mysql.source.config.MySqlSourceOptions;
+import org.apache.flink.api.common.functions.FlatMapFunction;
+import org.apache.flink.api.connector.source.Source;
+import org.apache.flink.configuration.Configuration;
+import org.apache.flink.connector.pulsar.common.config.PulsarOptions;
+import org.apache.flink.connector.pulsar.source.PulsarSourceOptions;
+import org.apache.flink.streaming.connectors.kafka.table.KafkaConnectorOptions;
+
+import java.util.List;
+import java.util.Map;
+
+import static
org.apache.paimon.flink.action.cdc.CdcActionCommonUtils.KAFKA_CONF;
+import static
org.apache.paimon.flink.action.cdc.CdcActionCommonUtils.MONGODB_CONF;
+import static
org.apache.paimon.flink.action.cdc.CdcActionCommonUtils.MYSQL_CONF;
+import static
org.apache.paimon.flink.action.cdc.CdcActionCommonUtils.PULSAR_CONF;
+import static
org.apache.paimon.flink.action.cdc.CdcActionCommonUtils.checkRequiredOptions;
+import static org.apache.paimon.utils.Preconditions.checkArgument;
+
+/** Provide different function according to CDC source type. */
+public class SyncJobHandler {
+
+ private final SourceType sourceType;
+ private final Configuration cdcSourceConfig;
+ private final boolean isTableSync;
+ private final String sinkLocation;
+
+ public SyncJobHandler(
+ SourceType sourceType, Map<String, String> cdcSourceConfig, String
database) {
+ this.sourceType = sourceType;
+ this.cdcSourceConfig = Configuration.fromMap(cdcSourceConfig);
+ this.isTableSync = false;
+ this.sinkLocation = database;
+ }
+
+ public SyncJobHandler(
+ SourceType sourceType,
+ Map<String, String> cdcSourceConfig,
+ String database,
+ String table) {
+ this.sourceType = sourceType;
+ this.cdcSourceConfig = Configuration.fromMap(cdcSourceConfig);
+ this.isTableSync = true;
+ this.sinkLocation = database + "." + table;
+ }
+
+ public String provideSourceName() {
+ return sourceType.sourceName;
+ }
+
+ public String provideDefaultJobName() {
+ return String.format(
+ sourceType.defaultJobNameFormat, isTableSync ? "Table" :
"Database", sinkLocation);
+ }
+
+ public void registerJdbcDriver() {
+ if (sourceType == SourceType.MYSQL) {
+ MySqlActionUtils.registerJdbcDriver();
+ }
+ }
+
+ public void checkRequiredOption() {
+ switch (sourceType) {
+ case MYSQL:
+ checkRequiredOptions(
+ cdcSourceConfig,
+ MYSQL_CONF,
+ MySqlSourceOptions.HOSTNAME,
+ MySqlSourceOptions.PORT,
+ MySqlSourceOptions.USERNAME,
+ MySqlSourceOptions.PASSWORD,
+ MySqlSourceOptions.DATABASE_NAME);
+ if (isTableSync) {
+ checkRequiredOptions(
+ cdcSourceConfig, MYSQL_CONF,
MySqlSourceOptions.TABLE_NAME);
+ } else {
+ checkArgument(
+
!cdcSourceConfig.contains(MySqlSourceOptions.TABLE_NAME),
+ MySqlSourceOptions.TABLE_NAME.key()
+ + " cannot be set for mysql_sync_database.
"
+ + "If you want to sync several MySQL
tables into one Paimon table, "
+ + "use mysql_sync_table instead.");
+ }
+ break;
+ case KAFKA:
+ checkRequiredOptions(
+ cdcSourceConfig,
+ KAFKA_CONF,
+ KafkaConnectorOptions.VALUE_FORMAT,
+ KafkaConnectorOptions.TOPIC,
+ KafkaConnectorOptions.PROPS_BOOTSTRAP_SERVERS);
+ break;
+ case PULSAR:
+ checkRequiredOptions(
+ cdcSourceConfig,
+ PULSAR_CONF,
+ PulsarActionUtils.TOPIC,
+ PulsarActionUtils.VALUE_FORMAT,
+ PulsarOptions.PULSAR_SERVICE_URL,
+ PulsarOptions.PULSAR_ADMIN_URL,
+ PulsarSourceOptions.PULSAR_SUBSCRIPTION_NAME);
+ break;
+ case MONGODB:
+ checkRequiredOptions(
+ cdcSourceConfig,
+ MONGODB_CONF,
+ MongoDBSourceOptions.HOSTS,
+ MongoDBSourceOptions.DATABASE);
+ if (isTableSync) {
+ checkRequiredOptions(
+ cdcSourceConfig, MONGODB_CONF,
MongoDBSourceOptions.COLLECTION);
+ }
+ break;
+ default:
+ throw new UnsupportedOperationException("Unknown source type "
+ sourceType);
+ }
+ }
+
+ public Source<String, ?, ?> provideSource() {
+ switch (sourceType) {
+ case KAFKA:
+ return KafkaActionUtils.buildKafkaSource(cdcSourceConfig);
+ case PULSAR:
+ return PulsarActionUtils.buildPulsarSource(cdcSourceConfig);
+ default:
+ throw new UnsupportedOperationException(
+ "Cannot get source from source type" + sourceType);
+ }
+ }
+
+ public FlatMapFunction<String, RichCdcMultiplexRecord> provideRecordParser(
+ boolean caseSensitive,
+ List<ComputedColumn> computedColumns,
+ TypeMapping typeMapping,
+ CdcMetadataConverter[] metadataConverters) {
+ switch (sourceType) {
+ case MYSQL:
+ return new MySqlRecordParser(
+ cdcSourceConfig,
+ caseSensitive,
+ computedColumns,
+ typeMapping,
+ metadataConverters);
+ case KAFKA:
+ case PULSAR:
+ DataFormat dataFormat = provideDataFormat();
+ return dataFormat.createParser(caseSensitive, typeMapping,
computedColumns);
+ case MONGODB:
+ return new MongoDBRecordParser(caseSensitive, computedColumns,
cdcSourceConfig);
+ default:
+ throw new UnsupportedOperationException("Unknown source type "
+ sourceType);
+ }
+ }
+
+ public DataFormat provideDataFormat() {
+ switch (sourceType) {
+ case KAFKA:
+ return KafkaActionUtils.getDataFormat(cdcSourceConfig);
+ case PULSAR:
+ return PulsarActionUtils.getDataFormat(cdcSourceConfig);
+ default:
+ throw new UnsupportedOperationException(
+ "Cannot get DataFormat from source type" + sourceType);
+ }
+ }
+
+ public MessageQueueSchemaUtils.ConsumerWrapper provideConsumer() {
+ switch (sourceType) {
+ case KAFKA:
+ return
KafkaActionUtils.getKafkaEarliestConsumer(cdcSourceConfig);
+ case PULSAR:
+ return PulsarActionUtils.createPulsarConsumer(cdcSourceConfig);
+ default:
+ throw new UnsupportedOperationException(
+ "Cannot get consumer from source type" + sourceType);
+ }
+ }
+
+ /** CDC source type. */
+ public enum SourceType {
+ MYSQL("MySQL Source", "MySQL-Paimon %s Sync: %s"),
+ KAFKA("Kafka Source", "Kafka-Paimon %s Sync: %s"),
+ MONGODB("MongoDB Source", "MongoDB-Paimon %s Sync: %s"),
+ PULSAR("Pulsar Source", "Pulsar-Paimon %s Sync: %s");
+
+ private final String sourceName;
+ private final String defaultJobNameFormat;
+
+ SourceType(String sourceName, String defaultJobNameFormat) {
+ this.sourceName = sourceName;
+ this.defaultJobNameFormat = defaultJobNameFormat;
+ }
+ }
+}
diff --git
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/SyncTableActionBase.java
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/SyncTableActionBase.java
index 82510f15a..317304b28 100644
---
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/SyncTableActionBase.java
+++
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/SyncTableActionBase.java
@@ -23,7 +23,6 @@ import org.apache.paimon.catalog.AbstractCatalog;
import org.apache.paimon.catalog.Identifier;
import org.apache.paimon.flink.FlinkConnectorOptions;
import org.apache.paimon.flink.action.Action;
-import org.apache.paimon.flink.action.ActionBase;
import org.apache.paimon.flink.sink.cdc.CdcSinkBuilder;
import org.apache.paimon.flink.sink.cdc.EventParser;
import org.apache.paimon.flink.sink.cdc.RichCdcMultiplexRecord;
@@ -31,60 +30,47 @@ import
org.apache.paimon.flink.sink.cdc.RichCdcMultiplexRecordEventParser;
import org.apache.paimon.schema.Schema;
import org.apache.paimon.table.FileStoreTable;
-import org.apache.flink.api.common.eventtime.WatermarkStrategy;
import org.apache.flink.api.common.functions.FlatMapFunction;
-import org.apache.flink.api.connector.source.Source;
-import org.apache.flink.configuration.Configuration;
import org.apache.flink.streaming.api.datastream.DataStream;
-import org.apache.flink.streaming.api.datastream.DataStreamSource;
-import org.apache.flink.streaming.api.functions.source.SourceFunction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.Optional;
-import java.util.stream.Collectors;
import static
org.apache.paimon.flink.action.cdc.CdcActionCommonUtils.assertSchemaCompatible;
import static
org.apache.paimon.flink.action.cdc.ComputedColumnUtils.buildComputedColumns;
-import static org.apache.paimon.utils.Preconditions.checkArgument;
import static org.apache.paimon.utils.Preconditions.checkState;
/** Base {@link Action} for synchronizing into one Paimon table. */
-public abstract class SyncTableActionBase extends ActionBase {
+public abstract class SyncTableActionBase extends SynchronizationActionBase {
private static final Logger LOG =
LoggerFactory.getLogger(SyncTableActionBase.class);
- protected final String database;
protected final String table;
- protected final Configuration cdcSourceConfig;
- protected FileStoreTable fileStoreTable;
+ protected FileStoreTable fileStoreTable;
protected List<String> partitionKeys = new ArrayList<>();
protected List<String> primaryKeys = new ArrayList<>();
-
- protected Map<String, String> tableConfig = new HashMap<>();
protected List<String> computedColumnArgs = new ArrayList<>();
- protected TypeMapping typeMapping = TypeMapping.defaultMapping();
-
protected List<ComputedColumn> computedColumns = new ArrayList<>();
- protected CdcMetadataConverter[] metadataConverters = new
CdcMetadataConverter[] {};
public SyncTableActionBase(
String warehouse,
String database,
String table,
Map<String, String> catalogConfig,
- Map<String, String> cdcSourceConfig) {
- super(warehouse, catalogConfig);
- this.database = database;
+ Map<String, String> cdcSourceConfig,
+ SyncJobHandler.SourceType sourceType) {
+ super(
+ warehouse,
+ database,
+ catalogConfig,
+ cdcSourceConfig,
+ new SyncJobHandler(sourceType, cdcSourceConfig, database,
table));
this.table = table;
- this.cdcSourceConfig = Configuration.fromMap(cdcSourceConfig);
}
public SyncTableActionBase withPartitionKeys(String... partitionKeys) {
@@ -105,37 +91,11 @@ public abstract class SyncTableActionBase extends
ActionBase {
return this;
}
- public SyncTableActionBase withTableConfig(Map<String, String>
tableConfig) {
- this.tableConfig = tableConfig;
- return this;
- }
-
public SyncTableActionBase withComputedColumnArgs(List<String>
computedColumnArgs) {
this.computedColumnArgs = computedColumnArgs;
return this;
}
- public SyncTableActionBase withTypeMapping(TypeMapping typeMapping) {
- this.typeMapping = typeMapping;
- return this;
- }
-
- public SyncTableActionBase withMetadataColumns(List<String>
metadataColumns) {
- this.metadataConverters =
- metadataColumns.stream()
- .map(this::metadataConverter)
- .filter(Optional::isPresent)
- .map(Optional::get)
- .toArray(CdcMetadataConverter[]::new);
- return this;
- }
-
- protected Optional<CdcMetadataConverter<?>> metadataConverter(String
column) {
- return Optional.empty();
- }
-
- protected void checkCdcSourceArgument() {}
-
protected abstract Schema retrieveSchema() throws Exception;
protected Schema buildPaimonSchema(Schema retrievedSchema) {
@@ -149,26 +109,22 @@ public abstract class SyncTableActionBase extends
ActionBase {
true);
}
- protected abstract DataStreamSource<String> buildSource() throws Exception;
-
- protected abstract String sourceName();
-
- protected abstract FlatMapFunction<String, RichCdcMultiplexRecord>
recordParse();
-
@Override
- public void build() throws Exception {
- checkCdcSourceArgument();
- catalog.createDatabase(database, true);
-
- boolean caseSensitive = catalog.caseSensitive();
-
- validateCaseInsensitive(caseSensitive);
+ protected void validateCaseSensitivity() {
+ AbstractCatalog.validateCaseInsensitive(caseSensitive, "Database",
database);
+ AbstractCatalog.validateCaseInsensitive(caseSensitive, "Table", table);
+ AbstractCatalog.validateCaseInsensitive(caseSensitive, "Partition
keys", partitionKeys);
+ AbstractCatalog.validateCaseInsensitive(caseSensitive, "Primary keys",
primaryKeys);
+ }
+ @Override
+ protected void beforeBuildingSourceSink() throws Exception {
Identifier identifier = new Identifier(database, table);
// Check if table exists before trying to get or create it
if (catalog.tableExists(identifier)) {
fileStoreTable = (FileStoreTable)
catalog.getTable(identifier).copy(tableConfig);
try {
+ // TODO: test case insensitive with computed columns
Schema retrievedSchema = retrieveSchema();
computedColumns =
buildComputedColumns(computedColumnArgs,
retrievedSchema.fields());
@@ -180,6 +136,7 @@ public abstract class SyncTableActionBase extends
ActionBase {
+ "Schema compatibility check will be skipped.
If you have specified computed columns, "
+ "here will use the existed Paimon table
schema to build them. Please make sure "
+ "the Paimon table has defined all the
argument columns used for computed columns.");
+ // schema evolution will add the computed columns
computedColumns =
buildComputedColumns(computedColumnArgs,
fileStoreTable.schema().fields());
// check partition keys and primary keys in case that user
specified them
@@ -192,20 +149,30 @@ public abstract class SyncTableActionBase extends
ActionBase {
catalog.createTable(identifier, paimonSchema, false);
fileStoreTable = (FileStoreTable)
catalog.getTable(identifier).copy(tableConfig);
}
+ }
- checkComputedColumns(computedColumns);
+ @Override
+ protected FlatMapFunction<String, RichCdcMultiplexRecord> recordParse() {
+ return syncJobHandler.provideRecordParser(
+ caseSensitive, computedColumns, typeMapping,
metadataConverters);
+ }
- DataStream<RichCdcMultiplexRecord> input =
- buildSource().flatMap(recordParse()).name("Parse");
- EventParser.Factory<RichCdcMultiplexRecord> parserFactory =
- () -> new RichCdcMultiplexRecordEventParser(caseSensitive);
+ @Override
+ protected EventParser.Factory<RichCdcMultiplexRecord>
buildEventParserFactory() {
+ boolean caseSensitive = this.caseSensitive;
+ return () -> new RichCdcMultiplexRecordEventParser(caseSensitive);
+ }
+ @Override
+ protected void buildSink(
+ DataStream<RichCdcMultiplexRecord> input,
+ EventParser.Factory<RichCdcMultiplexRecord> parserFactory) {
CdcSinkBuilder<RichCdcMultiplexRecord> sinkBuilder =
new CdcSinkBuilder<RichCdcMultiplexRecord>()
.withInput(input)
.withParserFactory(parserFactory)
.withTable(fileStoreTable)
- .withIdentifier(identifier)
+ .withIdentifier(new Identifier(database, table))
.withCatalogLoader(catalogLoader());
String sinkParallelism =
tableConfig.get(FlinkConnectorOptions.SINK_PARALLELISM.key());
if (sinkParallelism != null) {
@@ -214,39 +181,6 @@ public abstract class SyncTableActionBase extends
ActionBase {
sinkBuilder.build();
}
- protected DataStreamSource<String> buildDataStreamSource(Object source) {
- if (source instanceof Source) {
- return env.fromSource(
- (Source<String, ?, ?>) source,
WatermarkStrategy.noWatermarks(), sourceName());
- }
- if (source instanceof SourceFunction) {
- return env.addSource((SourceFunction<String>) source,
sourceName());
- }
- throw new UnsupportedOperationException("Unrecognized source type");
- }
-
- protected void validateCaseInsensitive(boolean caseSensitive) {
- AbstractCatalog.validateCaseInsensitive(caseSensitive, "Database",
database);
- AbstractCatalog.validateCaseInsensitive(caseSensitive, "Table", table);
- AbstractCatalog.validateCaseInsensitive(caseSensitive, "Partition
keys", partitionKeys);
- AbstractCatalog.validateCaseInsensitive(caseSensitive, "Primary keys",
primaryKeys);
- }
-
- protected void checkComputedColumns(List<ComputedColumn> computedColumns) {
- if (!computedColumns.isEmpty()) {
- List<String> computedFields =
- computedColumns.stream()
- .map(ComputedColumn::columnName)
- .collect(Collectors.toList());
- List<String> fieldNames = fileStoreTable.schema().fieldNames();
- checkArgument(
- new HashSet<>(fieldNames).containsAll(computedFields),
- " Exists Table should contain all computed columns %s, but
are %s.",
- computedFields,
- fieldNames);
- }
- }
-
private void checkConstraints() {
if (!partitionKeys.isEmpty()) {
List<String> actualPartitionKeys = fileStoreTable.partitionKeys();
@@ -271,28 +205,11 @@ public abstract class SyncTableActionBase extends
ActionBase {
}
}
- @VisibleForTesting
- public Map<String, String> tableConfig() {
- return tableConfig;
- }
-
@VisibleForTesting
public FileStoreTable fileStoreTable() {
return fileStoreTable;
}
- // ------------------------------------------------------------------------
- // Flink run methods
- // ------------------------------------------------------------------------
-
- protected abstract String jobName();
-
- @Override
- public void run() throws Exception {
- build();
- execute(jobName());
- }
-
/** Custom exception to indicate issues with schema retrieval. */
public static class SchemaRetrievalException extends Exception {
public SchemaRetrievalException(String message) {
diff --git
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/SynchronizationActionBase.java
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/SynchronizationActionBase.java
new file mode 100644
index 000000000..3cc77e6f5
--- /dev/null
+++
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/SynchronizationActionBase.java
@@ -0,0 +1,154 @@
+/*
+ * 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.paimon.flink.action.cdc;
+
+import org.apache.paimon.annotation.VisibleForTesting;
+import org.apache.paimon.flink.action.Action;
+import org.apache.paimon.flink.action.ActionBase;
+import org.apache.paimon.flink.sink.cdc.EventParser;
+import org.apache.paimon.flink.sink.cdc.RichCdcMultiplexRecord;
+
+import org.apache.flink.api.common.eventtime.WatermarkStrategy;
+import org.apache.flink.api.common.functions.FlatMapFunction;
+import org.apache.flink.api.connector.source.Source;
+import org.apache.flink.configuration.Configuration;
+import org.apache.flink.streaming.api.datastream.DataStream;
+import org.apache.flink.streaming.api.datastream.DataStreamSource;
+import org.apache.flink.streaming.api.functions.source.SourceFunction;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+/** Base {@link Action} for table/database synchronizing job. */
+public abstract class SynchronizationActionBase extends ActionBase {
+
+ private static final long DEFAULT_CHECKPOINT_INTERVAL = 3 * 60 * 1000;
+
+ protected final String database;
+ protected final Configuration cdcSourceConfig;
+ protected final SyncJobHandler syncJobHandler;
+ protected final boolean caseSensitive;
+
+ protected Map<String, String> tableConfig = new HashMap<>();
+ protected TypeMapping typeMapping = TypeMapping.defaultMapping();
+ protected CdcMetadataConverter[] metadataConverters = new
CdcMetadataConverter[] {};
+
+ public SynchronizationActionBase(
+ String warehouse,
+ String database,
+ Map<String, String> catalogConfig,
+ Map<String, String> cdcSourceConfig,
+ SyncJobHandler syncJobHandler) {
+ super(warehouse, catalogConfig);
+ this.database = database;
+ this.cdcSourceConfig = Configuration.fromMap(cdcSourceConfig);
+ this.syncJobHandler = syncJobHandler;
+ this.caseSensitive = catalog.caseSensitive();
+
+ this.syncJobHandler.registerJdbcDriver();
+ }
+
+ public SynchronizationActionBase withTableConfig(Map<String, String>
tableConfig) {
+ this.tableConfig = tableConfig;
+ return this;
+ }
+
+ public SynchronizationActionBase withTypeMapping(TypeMapping typeMapping) {
+ this.typeMapping = typeMapping;
+ return this;
+ }
+
+ public SynchronizationActionBase withMetadataColumns(List<String>
metadataColumns) {
+ this.metadataConverters =
+ metadataColumns.stream()
+ .map(this::metadataConverter)
+ .filter(Optional::isPresent)
+ .map(Optional::get)
+ .toArray(CdcMetadataConverter[]::new);
+ return this;
+ }
+
+ protected Optional<CdcMetadataConverter<?>> metadataConverter(String
column) {
+ return Optional.empty();
+ }
+
+ @VisibleForTesting
+ public Map<String, String> tableConfig() {
+ return tableConfig;
+ }
+
+ @Override
+ public void build() throws Exception {
+ syncJobHandler.checkRequiredOption();
+
+ catalog.createDatabase(database, true);
+
+ validateCaseSensitivity();
+
+ beforeBuildingSourceSink();
+
+ DataStream<RichCdcMultiplexRecord> input =
+
buildDataStreamSource(buildSource()).flatMap(recordParse()).name("Parse");
+
+ EventParser.Factory<RichCdcMultiplexRecord> parserFactory =
buildEventParserFactory();
+
+ buildSink(input, parserFactory);
+ }
+
+ protected abstract void validateCaseSensitivity();
+
+ protected void beforeBuildingSourceSink() throws Exception {}
+
+ protected Object buildSource() {
+ return syncJobHandler.provideSource();
+ }
+
+ private DataStreamSource<String> buildDataStreamSource(Object source) {
+ if (source instanceof Source) {
+ return env.fromSource(
+ (Source<String, ?, ?>) source,
+ WatermarkStrategy.noWatermarks(),
+ syncJobHandler.provideSourceName());
+ }
+ if (source instanceof SourceFunction) {
+ return env.addSource(
+ (SourceFunction<String>) source,
syncJobHandler.provideSourceName());
+ }
+ throw new UnsupportedOperationException("Unrecognized source type");
+ }
+
+ protected abstract FlatMapFunction<String, RichCdcMultiplexRecord>
recordParse();
+
+ protected abstract EventParser.Factory<RichCdcMultiplexRecord>
buildEventParserFactory();
+
+ protected abstract void buildSink(
+ DataStream<RichCdcMultiplexRecord> input,
+ EventParser.Factory<RichCdcMultiplexRecord> parserFactory);
+
+ @Override
+ public void run() throws Exception {
+ build();
+ if (!env.getCheckpointConfig().isCheckpointingEnabled()) {
+ env.enableCheckpointing(DEFAULT_CHECKPOINT_INTERVAL);
+ }
+ execute(syncJobHandler.provideDefaultJobName());
+ }
+}
diff --git
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/kafka/KafkaActionUtils.java
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/kafka/KafkaActionUtils.java
index c40fd5f39..8b98c8c06 100644
---
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/kafka/KafkaActionUtils.java
+++
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/kafka/KafkaActionUtils.java
@@ -32,7 +32,6 @@ import
org.apache.flink.streaming.connectors.kafka.table.KafkaConnectorOptions;
import
org.apache.flink.streaming.connectors.kafka.table.KafkaConnectorOptions.ScanStartupMode;
import org.apache.flink.table.api.TableException;
import org.apache.flink.table.api.ValidationException;
-import org.apache.flink.util.CollectionUtil;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
@@ -56,7 +55,6 @@ import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import static
org.apache.flink.streaming.connectors.kafka.table.KafkaConnectorOptions.SCAN_STARTUP_SPECIFIC_OFFSETS;
-import static org.apache.paimon.utils.Preconditions.checkArgument;
/** Utils for Kafka Action. */
public class KafkaActionUtils {
@@ -67,7 +65,6 @@ public class KafkaActionUtils {
private static final String OFFSET = "offset";
public static KafkaSource<String> buildKafkaSource(Configuration
kafkaConfig) {
- validateKafkaConfig(kafkaConfig);
KafkaSourceBuilder<String> kafkaSourceBuilder = KafkaSource.builder();
List<String> topics =
@@ -228,25 +225,6 @@ public class KafkaActionUtils {
return offsetMap;
}
- private static void validateKafkaConfig(Configuration kafkaConfig) {
- checkArgument(
- kafkaConfig.get(KafkaConnectorOptions.VALUE_FORMAT) != null,
- String.format(
- "kafka-conf [%s] must be specified.",
- KafkaConnectorOptions.VALUE_FORMAT.key()));
-
- checkArgument(
-
!CollectionUtil.isNullOrEmpty(kafkaConfig.get(KafkaConnectorOptions.TOPIC)),
- String.format(
- "kafka-conf [%s] must be specified.",
KafkaConnectorOptions.TOPIC.key()));
-
- checkArgument(
- kafkaConfig.get(KafkaConnectorOptions.PROPS_BOOTSTRAP_SERVERS)
!= null,
- String.format(
- "kafka-conf [%s] must be specified.",
- KafkaConnectorOptions.PROPS_BOOTSTRAP_SERVERS.key()));
- }
-
private static String kafkaPropertiesGroupId(Configuration kafkaConfig) {
String groupId = kafkaConfig.get(KafkaConnectorOptions.PROPS_GROUP_ID);
if (StringUtils.isEmpty(groupId)) {
@@ -256,12 +234,12 @@ public class KafkaActionUtils {
return groupId;
}
- static DataFormat getDataFormat(Configuration kafkaConfig) {
+ public static DataFormat getDataFormat(Configuration kafkaConfig) {
return
DataFormat.fromConfigString(kafkaConfig.get(KafkaConnectorOptions.VALUE_FORMAT));
}
- static MessageQueueSchemaUtils.ConsumerWrapper getKafkaEarliestConsumer(
- Configuration kafkaConfig, String topic) {
+ public static MessageQueueSchemaUtils.ConsumerWrapper
getKafkaEarliestConsumer(
+ Configuration kafkaConfig) {
Properties props = new Properties();
props.put(
ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,
@@ -275,6 +253,7 @@ public class KafkaActionUtils {
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
+ String topic = kafkaConfig.get(KafkaConnectorOptions.TOPIC).get(0);
// the return may be null in older versions of the Kafka client
List<PartitionInfo> partitionInfos = consumer.partitionsFor(topic);
if (partitionInfos == null || partitionInfos.isEmpty()) {
@@ -291,19 +270,21 @@ public class KafkaActionUtils {
consumer.assign(topicPartitions);
consumer.seekToBeginning(topicPartitions);
- return new KafkaConsumerWrapper(consumer);
+ return new KafkaConsumerWrapper(consumer, topic);
}
private static class KafkaConsumerWrapper implements
MessageQueueSchemaUtils.ConsumerWrapper {
private final KafkaConsumer<String, String> consumer;
+ private final String topic;
- KafkaConsumerWrapper(KafkaConsumer<String, String> kafkaConsumer) {
+ KafkaConsumerWrapper(KafkaConsumer<String, String> kafkaConsumer,
String topic) {
this.consumer = kafkaConsumer;
+ this.topic = topic;
}
@Override
- public List<String> getRecords(String topic, int pollTimeOutMills) {
+ public List<String> getRecords(int pollTimeOutMills) {
ConsumerRecords<String, String> consumerRecords =
consumer.poll(Duration.ofMillis(pollTimeOutMills));
return
StreamSupport.stream(consumerRecords.records(topic).spliterator(), false)
@@ -311,6 +292,11 @@ public class KafkaActionUtils {
.collect(Collectors.toList());
}
+ @Override
+ public String topic() {
+ return topic;
+ }
+
@Override
public void close() {
consumer.close();
diff --git
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/kafka/KafkaSyncDatabaseAction.java
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/kafka/KafkaSyncDatabaseAction.java
index 88419bc1b..4c87307e3 100644
---
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/kafka/KafkaSyncDatabaseAction.java
+++
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/kafka/KafkaSyncDatabaseAction.java
@@ -18,45 +18,19 @@
package org.apache.paimon.flink.action.cdc.kafka;
-import org.apache.paimon.flink.action.cdc.MessageQueueSyncDatabaseActionBase;
-import org.apache.paimon.flink.action.cdc.format.DataFormat;
-
-import org.apache.flink.api.common.eventtime.WatermarkStrategy;
-import org.apache.flink.streaming.api.datastream.DataStreamSource;
+import org.apache.paimon.flink.action.cdc.SyncDatabaseActionBase;
+import org.apache.paimon.flink.action.cdc.SyncJobHandler;
import java.util.Map;
/** Synchronize database from Kafka. */
-public class KafkaSyncDatabaseAction extends
MessageQueueSyncDatabaseActionBase {
+public class KafkaSyncDatabaseAction extends SyncDatabaseActionBase {
public KafkaSyncDatabaseAction(
String warehouse,
String database,
Map<String, String> catalogConfig,
Map<String, String> kafkaConfig) {
- super(warehouse, database, catalogConfig, kafkaConfig);
- }
-
- @Override
- protected DataStreamSource<String> buildSource() throws Exception {
- return env.fromSource(
- KafkaActionUtils.buildKafkaSource(cdcSourceConfig),
- WatermarkStrategy.noWatermarks(),
- sourceName());
- }
-
- @Override
- protected String sourceName() {
- return "Kafka Source";
- }
-
- @Override
- protected DataFormat getDataFormat() {
- return KafkaActionUtils.getDataFormat(cdcSourceConfig);
- }
-
- @Override
- protected String jobName() {
- return String.format("Kafka-Paimon Database Sync: %s", database);
+ super(warehouse, database, catalogConfig, kafkaConfig,
SyncJobHandler.SourceType.KAFKA);
}
}
diff --git
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/kafka/KafkaSyncDatabaseActionFactory.java
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/kafka/KafkaSyncDatabaseActionFactory.java
index 700720ba1..7f787196b 100644
---
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/kafka/KafkaSyncDatabaseActionFactory.java
+++
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/kafka/KafkaSyncDatabaseActionFactory.java
@@ -53,11 +53,11 @@ public class KafkaSyncDatabaseActionFactory implements
ActionFactory {
optionalConfigMap(params, CATALOG_CONF),
optionalConfigMap(params, KAFKA_CONF));
- action.withTableConfig(optionalConfigMap(params, TABLE_CONF))
- .withTablePrefix(params.get(TABLE_PREFIX))
+ action.withTablePrefix(params.get(TABLE_PREFIX))
.withTableSuffix(params.get(TABLE_SUFFIX))
.includingTables(params.get(INCLUDING_TABLES))
- .excludingTables(params.get(EXCLUDING_TABLES));
+ .excludingTables(params.get(EXCLUDING_TABLES))
+ .withTableConfig(optionalConfigMap(params, TABLE_CONF));
if (params.has(TYPE_MAPPING)) {
String[] options = params.get(TYPE_MAPPING).split(",");
diff --git
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/kafka/KafkaSyncTableAction.java
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/kafka/KafkaSyncTableAction.java
index 0e90bda54..0c2d85407 100644
---
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/kafka/KafkaSyncTableAction.java
+++
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/kafka/KafkaSyncTableAction.java
@@ -18,12 +18,8 @@
package org.apache.paimon.flink.action.cdc.kafka;
-import org.apache.paimon.flink.action.cdc.MessageQueueSchemaUtils;
import org.apache.paimon.flink.action.cdc.MessageQueueSyncTableActionBase;
-import org.apache.paimon.flink.action.cdc.format.DataFormat;
-
-import org.apache.flink.streaming.api.datastream.DataStreamSource;
-import org.apache.flink.streaming.connectors.kafka.table.KafkaConnectorOptions;
+import org.apache.paimon.flink.action.cdc.SyncJobHandler;
import java.util.Map;
@@ -36,36 +32,12 @@ public class KafkaSyncTableAction extends
MessageQueueSyncTableActionBase {
String table,
Map<String, String> catalogConfig,
Map<String, String> kafkaConfig) {
- super(warehouse, database, table, catalogConfig, kafkaConfig);
- }
-
- @Override
- protected DataStreamSource<String> buildSource() {
- return
buildDataStreamSource(KafkaActionUtils.buildKafkaSource(cdcSourceConfig));
- }
-
- @Override
- protected String topic() {
- return cdcSourceConfig.get(KafkaConnectorOptions.TOPIC).get(0);
- }
-
- @Override
- protected MessageQueueSchemaUtils.ConsumerWrapper consumer(String topic) {
- return KafkaActionUtils.getKafkaEarliestConsumer(cdcSourceConfig,
topic);
- }
-
- @Override
- protected DataFormat getDataFormat() {
- return KafkaActionUtils.getDataFormat(cdcSourceConfig);
- }
-
- @Override
- protected String sourceName() {
- return "Kafka Source";
- }
-
- @Override
- protected String jobName() {
- return String.format("Kafka-Paimon Table Sync: %s.%s", database,
table);
+ super(
+ warehouse,
+ database,
+ table,
+ catalogConfig,
+ kafkaConfig,
+ SyncJobHandler.SourceType.KAFKA);
}
}
diff --git
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mongodb/MongoDBActionUtils.java
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mongodb/MongoDBActionUtils.java
index f667b3bbb..c1da23b0b 100644
---
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mongodb/MongoDBActionUtils.java
+++
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mongodb/MongoDBActionUtils.java
@@ -33,8 +33,6 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
-import static org.apache.paimon.utils.Preconditions.checkArgument;
-
/**
* Utility class for MongoDB-related actions.
*
@@ -87,7 +85,6 @@ public class MongoDBActionUtils {
public static MongoDBSource<String> buildMongodbSource(
Configuration mongodbConfig, String tableList) {
- validateMongodbConfig(mongodbConfig);
MongoDBSourceBuilder<String> sourceBuilder = MongoDBSource.builder();
if (mongodbConfig.contains(MongoDBSourceOptions.USERNAME)
@@ -140,17 +137,4 @@ public class MongoDBActionUtils {
return sourceBuilder.deserializer(schema).build();
}
-
- private static void validateMongodbConfig(Configuration mongodbConfig) {
- checkArgument(
- mongodbConfig.get(MongoDBSourceOptions.HOSTS) != null,
- String.format(
- "mongodb-conf [%s] must be specified.",
MongoDBSourceOptions.HOSTS.key()));
-
- checkArgument(
- mongodbConfig.get(MongoDBSourceOptions.DATABASE) != null,
- String.format(
- "mongodb-conf [%s] must be specified.",
- MongoDBSourceOptions.DATABASE.key()));
- }
}
diff --git
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mongodb/MongoDBRecordParser.java
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mongodb/MongoDBRecordParser.java
index 31ce83df1..1307c070a 100644
---
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mongodb/MongoDBRecordParser.java
+++
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mongodb/MongoDBRecordParser.java
@@ -30,7 +30,6 @@ import org.apache.flink.api.common.functions.FlatMapFunction;
import org.apache.flink.configuration.Configuration;
import org.apache.flink.util.Collector;
-import java.util.Collections;
import java.util.List;
/**
@@ -63,10 +62,6 @@ public class MongoDBRecordParser implements
FlatMapFunction<String, RichCdcMulti
private final Configuration mongodbConfig;
private JsonNode root;
- public MongoDBRecordParser(boolean caseSensitive, Configuration
mongodbConfig) {
- this(caseSensitive, Collections.emptyList(), mongodbConfig);
- }
-
public MongoDBRecordParser(
boolean caseSensitive,
List<ComputedColumn> computedColumns,
diff --git
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mongodb/MongoDBSyncDatabaseAction.java
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mongodb/MongoDBSyncDatabaseAction.java
index 2ced0edb9..3fcfccd07 100644
---
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mongodb/MongoDBSyncDatabaseAction.java
+++
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mongodb/MongoDBSyncDatabaseAction.java
@@ -18,19 +18,14 @@
package org.apache.paimon.flink.action.cdc.mongodb;
-import org.apache.paimon.catalog.Identifier;
import org.apache.paimon.flink.action.cdc.CdcActionCommonUtils;
import org.apache.paimon.flink.action.cdc.SyncDatabaseActionBase;
-import org.apache.paimon.flink.sink.cdc.RichCdcMultiplexRecord;
+import org.apache.paimon.flink.action.cdc.SyncJobHandler;
import com.ververica.cdc.connectors.mongodb.source.MongoDBSource;
import com.ververica.cdc.connectors.mongodb.source.config.MongoDBSourceOptions;
-import org.apache.flink.api.common.eventtime.WatermarkStrategy;
-import org.apache.flink.api.common.functions.FlatMapFunction;
-import org.apache.flink.streaming.api.datastream.DataStreamSource;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.Collections;
import java.util.Map;
/**
@@ -59,35 +54,16 @@ public class MongoDBSyncDatabaseAction extends
SyncDatabaseActionBase {
String database,
Map<String, String> catalogConfig,
Map<String, String> mongodbConfig) {
- super(warehouse, database, catalogConfig, mongodbConfig);
+ super(warehouse, database, catalogConfig, mongodbConfig,
SyncJobHandler.SourceType.MONGODB);
}
@Override
- protected DataStreamSource<String> buildSource() throws Exception {
- List<Identifier> excludedTables = new ArrayList<>();
- MongoDBSource<String> source =
- MongoDBActionUtils.buildMongodbSource(
- cdcSourceConfig,
- CdcActionCommonUtils.combinedModeTableList(
-
cdcSourceConfig.get(MongoDBSourceOptions.DATABASE),
- includingTables,
- excludedTables));
- return env.fromSource(source, WatermarkStrategy.noWatermarks(),
sourceName());
- }
-
- @Override
- protected String sourceName() {
- return "MongoDB Source";
- }
-
- @Override
- protected FlatMapFunction<String, RichCdcMultiplexRecord> recordParse() {
- boolean caseSensitive = catalog.caseSensitive();
- return new MongoDBRecordParser(caseSensitive, cdcSourceConfig);
- }
-
- @Override
- protected String jobName() {
- return String.format("MongoDB-Paimon Database Sync: %s", database);
+ protected MongoDBSource<String> buildSource() {
+ return MongoDBActionUtils.buildMongodbSource(
+ cdcSourceConfig,
+ CdcActionCommonUtils.combinedModeTableList(
+ cdcSourceConfig.get(MongoDBSourceOptions.DATABASE),
+ includingTables,
+ Collections.emptyList()));
}
}
diff --git
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mongodb/MongoDBSyncDatabaseActionFactory.java
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mongodb/MongoDBSyncDatabaseActionFactory.java
index e9c61582c..654572c48 100644
---
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mongodb/MongoDBSyncDatabaseActionFactory.java
+++
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mongodb/MongoDBSyncDatabaseActionFactory.java
@@ -50,11 +50,11 @@ public class MongoDBSyncDatabaseActionFactory implements
ActionFactory {
optionalConfigMap(params, CATALOG_CONF),
optionalConfigMap(params, MONGODB_CONF));
- action.withTableConfig(optionalConfigMap(params, TABLE_CONF))
- .withTablePrefix(params.get(TABLE_PREFIX))
+ action.withTablePrefix(params.get(TABLE_PREFIX))
.withTableSuffix(params.get(TABLE_SUFFIX))
.includingTables(params.get(INCLUDING_TABLES))
- .excludingTables(params.get(EXCLUDING_TABLES));
+ .excludingTables(params.get(EXCLUDING_TABLES))
+ .withTableConfig(optionalConfigMap(params, TABLE_CONF));
return Optional.of(action);
}
diff --git
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mongodb/MongoDBSyncTableAction.java
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mongodb/MongoDBSyncTableAction.java
index 08aacf9cc..7ee875f8d 100644
---
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mongodb/MongoDBSyncTableAction.java
+++
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mongodb/MongoDBSyncTableAction.java
@@ -18,18 +18,15 @@
package org.apache.paimon.flink.action.cdc.mongodb;
+import org.apache.paimon.flink.action.cdc.SyncJobHandler;
import org.apache.paimon.flink.action.cdc.SyncTableActionBase;
-import org.apache.paimon.flink.sink.cdc.RichCdcMultiplexRecord;
import org.apache.paimon.schema.Schema;
+import com.ververica.cdc.connectors.mongodb.source.MongoDBSource;
import com.ververica.cdc.connectors.mongodb.source.config.MongoDBSourceOptions;
-import org.apache.flink.api.common.functions.FlatMapFunction;
-import org.apache.flink.streaming.api.datastream.DataStreamSource;
import java.util.Map;
-import static org.apache.paimon.utils.Preconditions.checkArgument;
-
/**
* Represents an action to synchronize a specific MongoDB table with a target
system.
*
@@ -57,47 +54,26 @@ public class MongoDBSyncTableAction extends
SyncTableActionBase {
String table,
Map<String, String> catalogConfig,
Map<String, String> mongodbConfig) {
- super(warehouse, database, table, catalogConfig, mongodbConfig);
- }
-
- @Override
- protected void checkCdcSourceArgument() {
- checkArgument(
- cdcSourceConfig.contains(MongoDBSourceOptions.COLLECTION),
- String.format(
- "mongodb-conf [%s] must be specified.",
- MongoDBSourceOptions.COLLECTION.key()));
+ super(
+ warehouse,
+ database,
+ table,
+ catalogConfig,
+ mongodbConfig,
+ SyncJobHandler.SourceType.MONGODB);
}
@Override
- protected Schema retrieveSchema() throws Exception {
- boolean caseSensitive = catalog.caseSensitive();
+ protected Schema retrieveSchema() {
return MongodbSchemaUtils.getMongodbSchema(cdcSourceConfig,
caseSensitive);
}
@Override
- protected DataStreamSource<String> buildSource() throws Exception {
+ protected MongoDBSource<String> buildSource() {
String tableList =
cdcSourceConfig.get(MongoDBSourceOptions.DATABASE)
+ "\\."
+ cdcSourceConfig.get(MongoDBSourceOptions.COLLECTION);
- return buildDataStreamSource(
- MongoDBActionUtils.buildMongodbSource(cdcSourceConfig,
tableList));
- }
-
- @Override
- protected String sourceName() {
- return "MongoDB Source";
- }
-
- @Override
- protected FlatMapFunction<String, RichCdcMultiplexRecord> recordParse() {
- boolean caseSensitive = catalog.caseSensitive();
- return new MongoDBRecordParser(caseSensitive, computedColumns,
cdcSourceConfig);
- }
-
- @Override
- protected String jobName() {
- return String.format("MongoDB-Paimon Table Sync: %s.%s", database,
table);
+ return MongoDBActionUtils.buildMongodbSource(cdcSourceConfig,
tableList);
}
}
diff --git
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mysql/MySqlActionUtils.java
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mysql/MySqlActionUtils.java
index b5f5047b2..9cfa8eca8 100644
---
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mysql/MySqlActionUtils.java
+++
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mysql/MySqlActionUtils.java
@@ -53,7 +53,6 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static
org.apache.paimon.flink.action.cdc.TypeMapping.TypeMappingMode.TINYINT1_NOT_BOOL;
-import static org.apache.paimon.utils.Preconditions.checkArgument;
/** Utils for MySQL Action. */
public class MySqlActionUtils {
@@ -133,7 +132,6 @@ public class MySqlActionUtils {
public static MySqlSource<String> buildMySqlSource(
Configuration mySqlConfig, String tableList) {
- validateMySqlConfig(mySqlConfig);
MySqlSourceBuilder<String> sourceBuilder = MySqlSource.builder();
sourceBuilder
@@ -241,27 +239,4 @@ public class MySqlActionUtils {
}
}
}
-
- private static void validateMySqlConfig(Configuration mySqlConfig) {
- checkArgument(
- mySqlConfig.get(MySqlSourceOptions.HOSTNAME) != null,
- String.format(
- "mysql-conf [%s] must be specified.",
MySqlSourceOptions.HOSTNAME.key()));
-
- checkArgument(
- mySqlConfig.get(MySqlSourceOptions.USERNAME) != null,
- String.format(
- "mysql-conf [%s] must be specified.",
MySqlSourceOptions.USERNAME.key()));
-
- checkArgument(
- mySqlConfig.get(MySqlSourceOptions.PASSWORD) != null,
- String.format(
- "mysql-conf [%s] must be specified.",
MySqlSourceOptions.PASSWORD.key()));
-
- checkArgument(
- mySqlConfig.get(MySqlSourceOptions.DATABASE_NAME) != null,
- String.format(
- "mysql-conf [%s] must be specified.",
- MySqlSourceOptions.DATABASE_NAME.key()));
- }
}
diff --git
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mysql/MySqlRecordParser.java
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mysql/MySqlRecordParser.java
index 9f407173a..e5ba73e07 100644
---
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mysql/MySqlRecordParser.java
+++
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mysql/MySqlRecordParser.java
@@ -103,14 +103,6 @@ public class MySqlRecordParser implements
FlatMapFunction<String, RichCdcMultipl
private final Set<String> nonPkTables = new HashSet<>();
- public MySqlRecordParser(
- Configuration mySqlConfig,
- boolean caseSensitive,
- TypeMapping typeMapping,
- CdcMetadataConverter[] metadataConverters) {
- this(mySqlConfig, caseSensitive, Collections.emptyList(), typeMapping,
metadataConverters);
- }
-
public MySqlRecordParser(
Configuration mySqlConfig,
boolean caseSensitive,
diff --git
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mysql/MySqlSyncDatabaseAction.java
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mysql/MySqlSyncDatabaseAction.java
index e44aeb452..67bf7927b 100644
---
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mysql/MySqlSyncDatabaseAction.java
+++
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mysql/MySqlSyncDatabaseAction.java
@@ -25,10 +25,10 @@ import org.apache.paimon.flink.action.Action;
import org.apache.paimon.flink.action.cdc.CdcActionCommonUtils;
import org.apache.paimon.flink.action.cdc.CdcMetadataConverter;
import org.apache.paimon.flink.action.cdc.SyncDatabaseActionBase;
+import org.apache.paimon.flink.action.cdc.SyncJobHandler;
import org.apache.paimon.flink.action.cdc.TableNameConverter;
import org.apache.paimon.flink.action.cdc.mysql.schema.MySqlSchemasInfo;
import org.apache.paimon.flink.action.cdc.mysql.schema.MySqlTableInfo;
-import org.apache.paimon.flink.sink.cdc.RichCdcMultiplexRecord;
import org.apache.paimon.schema.Schema;
import org.apache.paimon.schema.TableSchema;
import org.apache.paimon.table.FileStoreTable;
@@ -36,9 +36,6 @@ import org.apache.paimon.utils.Preconditions;
import com.ververica.cdc.connectors.mysql.source.MySqlSource;
import com.ververica.cdc.connectors.mysql.source.config.MySqlSourceOptions;
-import org.apache.flink.api.common.eventtime.WatermarkStrategy;
-import org.apache.flink.api.common.functions.FlatMapFunction;
-import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -109,9 +106,8 @@ public class MySqlSyncDatabaseAction extends
SyncDatabaseActionBase {
String database,
Map<String, String> catalogConfig,
Map<String, String> mySqlConfig) {
- super(warehouse, database, catalogConfig, mySqlConfig);
+ super(warehouse, database, catalogConfig, mySqlConfig,
SyncJobHandler.SourceType.MYSQL);
this.mode = DIVIDED;
- MySqlActionUtils.registerJdbcDriver();
}
public MySqlSyncDatabaseAction ignoreIncompatible(boolean
ignoreIncompatible) {
@@ -125,17 +121,7 @@ public class MySqlSyncDatabaseAction extends
SyncDatabaseActionBase {
}
@Override
- protected void checkCdcSourceArgument() {
- checkArgument(
- !cdcSourceConfig.contains(MySqlSourceOptions.TABLE_NAME),
- MySqlSourceOptions.TABLE_NAME.key()
- + " cannot be set for mysql-sync-database. "
- + "If you want to sync several MySQL tables into one
Paimon table, "
- + "use mysql-sync-table instead.");
- }
-
- @Override
- protected DataStreamSource<String> buildSource() throws Exception {
+ protected void beforeBuildingSourceSink() throws Exception {
boolean caseSensitive = catalog.caseSensitive();
Pattern includingPattern = Pattern.compile(includingTables);
Pattern excludingPattern =
@@ -197,34 +183,18 @@ public class MySqlSyncDatabaseAction extends
SyncDatabaseActionBase {
!monitoredTables.isEmpty(),
"No tables to be synchronized. Possible cause is the schemas
of all tables in specified "
+ "MySQL database are not compatible with those of
existed Paimon tables. Please check the log.");
-
- MySqlSource<String> source =
- MySqlActionUtils.buildMySqlSource(
- cdcSourceConfig,
- tableList(
- mode,
-
cdcSourceConfig.get(MySqlSourceOptions.DATABASE_NAME),
- includingTables,
- monitoredTables,
- excludedTables));
- return env.fromSource(source, WatermarkStrategy.noWatermarks(),
sourceName());
- }
-
- @Override
- protected String sourceName() {
- return "MySQL Source";
- }
-
- @Override
- protected FlatMapFunction<String, RichCdcMultiplexRecord> recordParse() {
- boolean caseSensitive = catalog.caseSensitive();
- return new MySqlRecordParser(
- cdcSourceConfig, caseSensitive, typeMapping,
metadataConverters);
}
@Override
- protected String jobName() {
- return String.format("MySQL-Paimon Database Sync: %s", database);
+ protected MySqlSource<String> buildSource() {
+ return MySqlActionUtils.buildMySqlSource(
+ cdcSourceConfig,
+ tableList(
+ mode,
+ cdcSourceConfig.get(MySqlSourceOptions.DATABASE_NAME),
+ includingTables,
+ monitoredTables,
+ excludedTables));
}
private void logNonPkTables(List<Identifier> nonPkTables) {
diff --git
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mysql/MySqlSyncTableAction.java
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mysql/MySqlSyncTableAction.java
index 4d0f05664..b7510d08a 100644
---
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mysql/MySqlSyncTableAction.java
+++
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mysql/MySqlSyncTableAction.java
@@ -21,15 +21,14 @@ package org.apache.paimon.flink.action.cdc.mysql;
import org.apache.paimon.catalog.Identifier;
import org.apache.paimon.flink.action.Action;
import org.apache.paimon.flink.action.cdc.CdcMetadataConverter;
+import org.apache.paimon.flink.action.cdc.SyncJobHandler;
import org.apache.paimon.flink.action.cdc.SyncTableActionBase;
import org.apache.paimon.flink.action.cdc.mysql.schema.MySqlSchemasInfo;
import org.apache.paimon.flink.action.cdc.mysql.schema.MySqlTableInfo;
-import org.apache.paimon.flink.sink.cdc.RichCdcMultiplexRecord;
import org.apache.paimon.schema.Schema;
+import com.ververica.cdc.connectors.mysql.source.MySqlSource;
import com.ververica.cdc.connectors.mysql.source.config.MySqlSourceOptions;
-import org.apache.flink.api.common.functions.FlatMapFunction;
-import org.apache.flink.streaming.api.datastream.DataStreamSource;
import java.util.ArrayList;
import java.util.List;
@@ -82,8 +81,13 @@ public class MySqlSyncTableAction extends
SyncTableActionBase {
String table,
Map<String, String> catalogConfig,
Map<String, String> mySqlConfig) {
- super(warehouse, database, table, catalogConfig, mySqlConfig);
- MySqlActionUtils.registerJdbcDriver();
+ super(
+ warehouse,
+ database,
+ table,
+ catalogConfig,
+ mySqlConfig,
+ SyncJobHandler.SourceType.MYSQL);
}
@Override
@@ -91,14 +95,6 @@ public class MySqlSyncTableAction extends
SyncTableActionBase {
return Optional.of(MySqlMetadataProcessor.converter(column));
}
- @Override
- protected void checkCdcSourceArgument() {
- checkArgument(
- cdcSourceConfig.contains(MySqlSourceOptions.TABLE_NAME),
- String.format(
- "mysql-conf [%s] must be specified.",
MySqlSourceOptions.TABLE_NAME.key()));
- }
-
@Override
protected Schema retrieveSchema() throws Exception {
this.mySqlSchemasInfo =
@@ -107,36 +103,19 @@ public class MySqlSyncTableAction extends
SyncTableActionBase {
monitorTablePredication(),
new ArrayList<>(),
typeMapping,
- catalog.caseSensitive());
+ caseSensitive);
validateMySqlTableInfos(mySqlSchemasInfo);
MySqlTableInfo tableInfo = mySqlSchemasInfo.mergeAll();
return tableInfo.schema();
}
@Override
- protected DataStreamSource<String> buildSource() throws Exception {
+ protected MySqlSource<String> buildSource() {
String tableList =
mySqlSchemasInfo.pkTables().stream()
.map(i -> i.getDatabaseName() + "\\." +
i.getObjectName())
.collect(Collectors.joining("|"));
- return
buildDataStreamSource(MySqlActionUtils.buildMySqlSource(cdcSourceConfig,
tableList));
- }
-
- @Override
- protected String sourceName() {
- return "MySQL Source";
- }
-
- @Override
- protected FlatMapFunction<String, RichCdcMultiplexRecord> recordParse() {
- boolean caseSensitive = catalog.caseSensitive();
- return new MySqlRecordParser(
- cdcSourceConfig, caseSensitive, computedColumns, typeMapping,
metadataConverters);
- }
-
- @Override
- protected String jobName() {
- return String.format("MySQL-Paimon Table Sync: %s.%s", database,
table);
+ return MySqlActionUtils.buildMySqlSource(cdcSourceConfig, tableList);
}
private void validateMySqlTableInfos(MySqlSchemasInfo mySqlSchemasInfo) {
diff --git
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/pulsar/PulsarActionUtils.java
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/pulsar/PulsarActionUtils.java
index bc8bc3f01..11e979c8b 100644
---
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/pulsar/PulsarActionUtils.java
+++
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/pulsar/PulsarActionUtils.java
@@ -67,13 +67,13 @@ import static
org.apache.pulsar.client.api.KeySharedPolicy.stickyHashRange;
/** Utils for Pulsar synchronization. */
public class PulsarActionUtils {
- static final ConfigOption<String> VALUE_FORMAT =
+ public static final ConfigOption<String> VALUE_FORMAT =
ConfigOptions.key("value.format")
.stringType()
.noDefaultValue()
.withDescription("Defines the format identifier for
encoding value data.");
- static final ConfigOption<String> TOPIC =
+ public static final ConfigOption<String> TOPIC =
ConfigOptions.key("topic")
.stringType()
.noDefaultValue()
@@ -151,9 +151,8 @@ public class PulsarActionUtils {
.defaultValue(true)
.withDescription("To specify the boundedness of a
stream.");
- static PulsarSource<String> buildPulsarSource(Configuration rawConfig) {
+ public static PulsarSource<String> buildPulsarSource(Configuration
rawConfig) {
Configuration pulsarConfig = preprocessPulsarConfig(rawConfig);
- validatePulsarConfig(pulsarConfig);
PulsarSourceBuilder<String> pulsarSourceBuilder =
PulsarSource.builder();
@@ -261,29 +260,6 @@ public class PulsarActionUtils {
return pulsarSourceBuilder.build();
}
- private static void validatePulsarConfig(Configuration pulsarConfig) {
- checkArgument(
- pulsarConfig.contains(VALUE_FORMAT),
- String.format("pulsar-conf [%s] must be specified.",
VALUE_FORMAT.key()));
-
- checkArgument(
- pulsarConfig.contains(PULSAR_SERVICE_URL),
- String.format("pulsar-conf [%s] must be specified.",
PULSAR_SERVICE_URL.key()));
-
- checkArgument(
- pulsarConfig.contains(PULSAR_ADMIN_URL),
- String.format("pulsar-conf [%s] must be specified.",
PULSAR_ADMIN_URL.key()));
-
- checkArgument(
- pulsarConfig.contains(PULSAR_SUBSCRIPTION_NAME),
- String.format(
- "pulsar-conf [%s] must be specified.",
PULSAR_SUBSCRIPTION_NAME.key()));
-
- checkArgument(
- pulsarConfig.contains(TOPIC),
- String.format("pulsar-conf [%s] must be specified.",
TOPIC.key()));
- }
-
private static MessageId toMessageId(String messageIdString) {
if (messageIdString.equalsIgnoreCase("EARLIEST")) {
return MessageId.earliest;
@@ -317,56 +293,63 @@ public class PulsarActionUtils {
return cloned;
}
- static DataFormat getDataFormat(Configuration pulsarConfig) {
+ public static DataFormat getDataFormat(Configuration pulsarConfig) {
return DataFormat.fromConfigString(pulsarConfig.get(VALUE_FORMAT));
}
/** Referenced to {@link PulsarPartitionSplitReader#createPulsarConsumer}.
*/
- static MessageQueueSchemaUtils.ConsumerWrapper createPulsarConsumer(
- Configuration pulsarConfig, String topic) throws
PulsarClientException {
- SourceConfiguration pulsarSourceConfiguration =
toSourceConfiguration(pulsarConfig);
- PulsarClient pulsarClient =
PulsarClientFactory.createClient(pulsarSourceConfiguration);
-
- ConsumerBuilder<String> consumerBuilder =
- createConsumerBuilder(
- pulsarClient,
- org.apache.pulsar.client.api.Schema.STRING,
- pulsarSourceConfiguration);
-
- // The default position is Latest
-
consumerBuilder.subscriptionInitialPosition(SubscriptionInitialPosition.Earliest);
-
- TopicPartition topicPartition = new TopicPartition(topic);
- consumerBuilder.topic(topicPartition.getFullTopicName());
-
- // TODO currently, PulsarCrypto is not supported
-
- // Add KeySharedPolicy for partial keys subscription.
- if (!isFullTopicRanges(topicPartition.getRanges())) {
- KeySharedPolicy policy =
stickyHashRange().ranges(topicPartition.getPulsarRanges());
- // We may enable out of order delivery for speeding up. It was
turned off by
- // default.
- policy.setAllowOutOfOrderDelivery(
-
pulsarSourceConfiguration.isAllowKeySharedOutOfOrderDelivery());
- consumerBuilder.keySharedPolicy(policy);
- }
+ public static MessageQueueSchemaUtils.ConsumerWrapper createPulsarConsumer(
+ Configuration pulsarConfig) {
+ try {
+ SourceConfiguration pulsarSourceConfiguration =
toSourceConfiguration(pulsarConfig);
+ PulsarClient pulsarClient =
PulsarClientFactory.createClient(pulsarSourceConfiguration);
+
+ ConsumerBuilder<String> consumerBuilder =
+ createConsumerBuilder(
+ pulsarClient,
+ org.apache.pulsar.client.api.Schema.STRING,
+ pulsarSourceConfiguration);
+
+ // The default position is Latest
+
consumerBuilder.subscriptionInitialPosition(SubscriptionInitialPosition.Earliest);
+
+ String topic =
pulsarConfig.get(PulsarActionUtils.TOPIC).split(",")[0];
+ TopicPartition topicPartition = new TopicPartition(topic);
+ consumerBuilder.topic(topicPartition.getFullTopicName());
+
+ // TODO currently, PulsarCrypto is not supported
+
+ // Add KeySharedPolicy for partial keys subscription.
+ if (!isFullTopicRanges(topicPartition.getRanges())) {
+ KeySharedPolicy policy =
stickyHashRange().ranges(topicPartition.getPulsarRanges());
+ // We may enable out of order delivery for speeding up. It was
turned off by
+ // default.
+ policy.setAllowOutOfOrderDelivery(
+
pulsarSourceConfiguration.isAllowKeySharedOutOfOrderDelivery());
+ consumerBuilder.keySharedPolicy(policy);
+ }
- // Create the consumer configuration by using common utils.
- Consumer<String> consumer = consumerBuilder.subscribe();
+ // Create the consumer configuration by using common utils.
+ Consumer<String> consumer = consumerBuilder.subscribe();
- return new PulsarConsumerWrapper(consumer);
+ return new PulsarConsumerWrapper(consumer, topic);
+ } catch (PulsarClientException e) {
+ throw new RuntimeException(e);
+ }
}
private static class PulsarConsumerWrapper implements
MessageQueueSchemaUtils.ConsumerWrapper {
private final Consumer<String> consumer;
+ private final String topic;
- PulsarConsumerWrapper(Consumer<String> consumer) {
+ PulsarConsumerWrapper(Consumer<String> consumer, String topic) {
this.consumer = consumer;
+ this.topic = topic;
}
@Override
- public List<String> getRecords(String topic, int pollTimeOutMills) {
+ public List<String> getRecords(int pollTimeOutMills) {
try {
Message<String> message = consumer.receive(pollTimeOutMills,
TimeUnit.MILLISECONDS);
return message == null
@@ -377,6 +360,11 @@ public class PulsarActionUtils {
}
}
+ @Override
+ public String topic() {
+ return topic;
+ }
+
@Override
public void close() throws PulsarClientException {
consumer.close();
diff --git
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/pulsar/PulsarSyncDatabaseAction.java
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/pulsar/PulsarSyncDatabaseAction.java
index 589332cdf..fa7b7353e 100644
---
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/pulsar/PulsarSyncDatabaseAction.java
+++
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/pulsar/PulsarSyncDatabaseAction.java
@@ -18,45 +18,19 @@
package org.apache.paimon.flink.action.cdc.pulsar;
-import org.apache.paimon.flink.action.cdc.MessageQueueSyncDatabaseActionBase;
-import org.apache.paimon.flink.action.cdc.format.DataFormat;
-
-import org.apache.flink.api.common.eventtime.WatermarkStrategy;
-import org.apache.flink.streaming.api.datastream.DataStreamSource;
+import org.apache.paimon.flink.action.cdc.SyncDatabaseActionBase;
+import org.apache.paimon.flink.action.cdc.SyncJobHandler;
import java.util.Map;
/** Synchronize database from Pulsar. */
-public class PulsarSyncDatabaseAction extends
MessageQueueSyncDatabaseActionBase {
+public class PulsarSyncDatabaseAction extends SyncDatabaseActionBase {
public PulsarSyncDatabaseAction(
String warehouse,
String database,
Map<String, String> catalogConfig,
Map<String, String> pulsarConfig) {
- super(warehouse, database, catalogConfig, pulsarConfig);
- }
-
- @Override
- protected DataStreamSource<String> buildSource() throws Exception {
- return env.fromSource(
- PulsarActionUtils.buildPulsarSource(cdcSourceConfig),
- WatermarkStrategy.noWatermarks(),
- sourceName());
- }
-
- @Override
- protected DataFormat getDataFormat() {
- return PulsarActionUtils.getDataFormat(cdcSourceConfig);
- }
-
- @Override
- protected String sourceName() {
- return "Pulsar Source";
- }
-
- @Override
- protected String jobName() {
- return String.format("Pulsar-Paimon Database Sync: %s", database);
+ super(warehouse, database, catalogConfig, pulsarConfig,
SyncJobHandler.SourceType.PULSAR);
}
}
diff --git
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/pulsar/PulsarSyncDatabaseActionFactory.java
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/pulsar/PulsarSyncDatabaseActionFactory.java
index f042798ff..45301254a 100644
---
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/pulsar/PulsarSyncDatabaseActionFactory.java
+++
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/pulsar/PulsarSyncDatabaseActionFactory.java
@@ -53,11 +53,11 @@ public class PulsarSyncDatabaseActionFactory implements
ActionFactory {
optionalConfigMap(params, CATALOG_CONF),
optionalConfigMap(params, PULSAR_CONF));
- action.withTableConfig(optionalConfigMap(params, TABLE_CONF))
- .withTablePrefix(params.get(TABLE_PREFIX))
+ action.withTablePrefix(params.get(TABLE_PREFIX))
.withTableSuffix(params.get(TABLE_SUFFIX))
.includingTables(params.get(INCLUDING_TABLES))
- .excludingTables(params.get(EXCLUDING_TABLES));
+ .excludingTables(params.get(EXCLUDING_TABLES))
+ .withTableConfig(optionalConfigMap(params, TABLE_CONF));
if (params.has(TYPE_MAPPING)) {
String[] options = params.get(TYPE_MAPPING).split(",");
diff --git
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/pulsar/PulsarSyncTableAction.java
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/pulsar/PulsarSyncTableAction.java
index d21713828..c94c4581a 100644
---
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/pulsar/PulsarSyncTableAction.java
+++
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/pulsar/PulsarSyncTableAction.java
@@ -18,12 +18,8 @@
package org.apache.paimon.flink.action.cdc.pulsar;
-import org.apache.paimon.flink.action.cdc.MessageQueueSchemaUtils;
import org.apache.paimon.flink.action.cdc.MessageQueueSyncTableActionBase;
-import org.apache.paimon.flink.action.cdc.format.DataFormat;
-
-import org.apache.flink.streaming.api.datastream.DataStreamSource;
-import org.apache.pulsar.client.api.PulsarClientException;
+import org.apache.paimon.flink.action.cdc.SyncJobHandler;
import java.util.Map;
@@ -36,40 +32,12 @@ public class PulsarSyncTableAction extends
MessageQueueSyncTableActionBase {
String table,
Map<String, String> catalogConfig,
Map<String, String> pulsarConfig) {
- super(warehouse, database, table, catalogConfig, pulsarConfig);
- }
-
- @Override
- protected DataStreamSource<String> buildSource() {
- return
buildDataStreamSource(PulsarActionUtils.buildPulsarSource(cdcSourceConfig));
- }
-
- @Override
- protected String topic() {
- return
cdcSourceConfig.get(PulsarActionUtils.TOPIC).split(",")[0].trim();
- }
-
- @Override
- protected MessageQueueSchemaUtils.ConsumerWrapper consumer(String topic) {
- try {
- return PulsarActionUtils.createPulsarConsumer(cdcSourceConfig,
topic);
- } catch (PulsarClientException e) {
- throw new RuntimeException(e);
- }
- }
-
- @Override
- protected DataFormat getDataFormat() {
- return PulsarActionUtils.getDataFormat(cdcSourceConfig);
- }
-
- @Override
- protected String sourceName() {
- return "Pulsar Source";
- }
-
- @Override
- protected String jobName() {
- return String.format("Pulsar-Paimon Table Sync: %s.%s", database,
table);
+ super(
+ warehouse,
+ database,
+ table,
+ catalogConfig,
+ pulsarConfig,
+ SyncJobHandler.SourceType.PULSAR);
}
}
diff --git
a/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/kafka/KafkaCanalSyncDatabaseActionITCase.java
b/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/kafka/KafkaCanalSyncDatabaseActionITCase.java
index 2a0b6ef3c..fdc946565 100644
---
a/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/kafka/KafkaCanalSyncDatabaseActionITCase.java
+++
b/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/kafka/KafkaCanalSyncDatabaseActionITCase.java
@@ -252,7 +252,7 @@ public class KafkaCanalSyncDatabaseActionITCase extends
KafkaActionITCaseBase {
.satisfies(
anyCauseMatches(
IllegalArgumentException.class,
- "kafka-conf [topic] must be specified."));
+ "kafka_conf [topic] must be specified."));
}
@Test
diff --git
a/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/kafka/KafkaMaxwellSyncDatabaseActionITCase.java
b/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/kafka/KafkaMaxwellSyncDatabaseActionITCase.java
index d85217844..60ce40773 100644
---
a/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/kafka/KafkaMaxwellSyncDatabaseActionITCase.java
+++
b/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/kafka/KafkaMaxwellSyncDatabaseActionITCase.java
@@ -214,7 +214,7 @@ public class KafkaMaxwellSyncDatabaseActionITCase extends
KafkaActionITCaseBase
.satisfies(
AssertionUtils.anyCauseMatches(
IllegalArgumentException.class,
- "kafka-conf [topic] must be specified."));
+ "kafka_conf [topic] must be specified."));
}
@Test
diff --git
a/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/kafka/KafkaOggSyncDatabaseActionITCase.java
b/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/kafka/KafkaOggSyncDatabaseActionITCase.java
index d13c61b99..c930e1054 100644
---
a/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/kafka/KafkaOggSyncDatabaseActionITCase.java
+++
b/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/kafka/KafkaOggSyncDatabaseActionITCase.java
@@ -215,7 +215,7 @@ public class KafkaOggSyncDatabaseActionITCase extends
KafkaActionITCaseBase {
.satisfies(
AssertionUtils.anyCauseMatches(
IllegalArgumentException.class,
- "kafka-conf [topic] must be specified."));
+ "kafka_conf [topic] must be specified."));
}
@Test
diff --git
a/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/kafka/KafkaSchemaITCase.java
b/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/kafka/KafkaSchemaITCase.java
index a62a4380e..35eecbfad 100644
---
a/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/kafka/KafkaSchemaITCase.java
+++
b/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/kafka/KafkaSchemaITCase.java
@@ -61,8 +61,7 @@ public class KafkaSchemaITCase extends KafkaActionITCaseBase {
Schema kafkaSchema =
MessageQueueSchemaUtils.getSchema(
- getKafkaEarliestConsumer(kafkaConfig, topic),
- topic,
+ getKafkaEarliestConsumer(kafkaConfig),
getDataFormat(kafkaConfig),
TypeMapping.defaultMapping());
List<DataField> fields = new ArrayList<>();
diff --git
a/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/mysql/MySqlSyncDatabaseActionITCase.java
b/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/mysql/MySqlSyncDatabaseActionITCase.java
index 1dd87b121..5074e759d 100644
---
a/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/mysql/MySqlSyncDatabaseActionITCase.java
+++
b/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/mysql/MySqlSyncDatabaseActionITCase.java
@@ -212,9 +212,9 @@ public class MySqlSyncDatabaseActionITCase extends
MySqlActionITCaseBase {
assertThatThrownBy(action::run)
.isInstanceOf(IllegalArgumentException.class)
.hasMessage(
- "table-name cannot be set for mysql-sync-database. "
+ "table-name cannot be set for mysql_sync_database. "
+ "If you want to sync several MySQL tables
into one Paimon table, "
- + "use mysql-sync-table instead.");
+ + "use mysql_sync_table instead.");
}
@Test
diff --git
a/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/mysql/MySqlSyncTableActionITCase.java
b/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/mysql/MySqlSyncTableActionITCase.java
index c7a04fc97..e7abc8902 100644
---
a/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/mysql/MySqlSyncTableActionITCase.java
+++
b/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/mysql/MySqlSyncTableActionITCase.java
@@ -26,14 +26,18 @@ import org.apache.paimon.types.DataField;
import org.apache.paimon.types.DataType;
import org.apache.paimon.types.DataTypes;
import org.apache.paimon.types.RowType;
+import org.apache.paimon.utils.CommonTestUtils;
import org.apache.paimon.utils.JsonSerdeUtil;
+import org.apache.flink.api.common.restartstrategy.RestartStrategies;
import org.apache.flink.core.execution.JobClient;
+import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;
import java.sql.Statement;
+import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -960,4 +964,38 @@ public class MySqlSyncTableActionITCase extends
MySqlActionITCaseBase {
private FileStoreTable getFileStoreTable() throws Exception {
return getFileStoreTable(tableName);
}
+
+ @Test
+ @Timeout(60)
+ public void testDefaultCheckpointInterval() throws Exception {
+ Map<String, String> mySqlConfig = getBasicMySqlConfig();
+ mySqlConfig.put("database-name", "default_checkpoint");
+ mySqlConfig.put("table-name", "t");
+
+ StreamExecutionEnvironment env =
StreamExecutionEnvironment.getExecutionEnvironment();
+ env.setRestartStrategy(RestartStrategies.noRestart());
+
+ MySqlSyncTableAction action =
syncTableActionBuilder(mySqlConfig).build();
+ action.withStreamExecutionEnvironment(env);
+
+ Thread thread =
+ new Thread(
+ () -> {
+ try {
+ action.run();
+ } catch (Exception ignore) {
+ }
+ });
+ thread.start();
+
+ CommonTestUtils.waitUtil(
+ () -> env.getCheckpointConfig().isCheckpointingEnabled(),
+ Duration.ofSeconds(5),
+ Duration.ofMillis(100));
+
+ assertThat(env.getCheckpointInterval()).isEqualTo(3 * 60 * 1000);
+
+ thread.interrupt();
+ env.close();
+ }
}
diff --git
a/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/pulsar/PulsarSchemaITCase.java
b/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/pulsar/PulsarSchemaITCase.java
index 789f6b414..98dfea01a 100644
---
a/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/pulsar/PulsarSchemaITCase.java
+++
b/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/pulsar/PulsarSchemaITCase.java
@@ -56,8 +56,7 @@ public class PulsarSchemaITCase extends
PulsarActionITCaseBase {
Schema pulsarSchema =
MessageQueueSchemaUtils.getSchema(
- createPulsarConsumer(pulsarConfig, topic),
- topic,
+ createPulsarConsumer(pulsarConfig),
getDataFormat(pulsarConfig),
TypeMapping.defaultMapping());
List<DataField> fields = new ArrayList<>();
diff --git
a/paimon-flink/paimon-flink-cdc/src/test/resources/mysql/sync_table_setup.sql
b/paimon-flink/paimon-flink-cdc/src/test/resources/mysql/sync_table_setup.sql
index 3e67e9909..7990a0330 100644
---
a/paimon-flink/paimon-flink-cdc/src/test/resources/mysql/sync_table_setup.sql
+++
b/paimon-flink/paimon-flink-cdc/src/test/resources/mysql/sync_table_setup.sql
@@ -334,4 +334,17 @@ CREATE TABLE test_metadata_columns (
pk INT,
_date VARCHAR(10),
PRIMARY KEY (pk)
+);
+
+--
################################################################################
+-- testDefaultCheckpointInterval
+--
################################################################################
+
+CREATE DATABASE default_checkpoint;
+USE default_checkpoint;
+
+CREATE TABLE t (
+ pk INT,
+ v VARCHAR(10),
+ PRIMARY KEY (pk)
);
\ No newline at end of file