This is an automated email from the ASF dual-hosted git repository.
dockerzhang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/inlong.git
The following commit(s) were added to refs/heads/master by this push:
new 0791d2b868 [INLONG-9510][Manager] Supports doris database
synchronization (#9511)
0791d2b868 is described below
commit 0791d2b868b055c5a3aa7b6ebc27812729413fa5
Author: fuweng11 <[email protected]>
AuthorDate: Fri Dec 22 16:59:53 2023 +0800
[INLONG-9510][Manager] Supports doris database synchronization (#9511)
---
.../inlong/manager/common/consts/DataNodeType.java | 2 +
.../manager/pojo/node/doris/DorisDataNodeDTO.java | 68 +++++++++++++++++
.../manager/pojo/node/doris/DorisDataNodeInfo.java | 49 +++++++++++++
.../pojo/node/doris/DorisDataNodeRequest.java | 39 ++++++++++
.../pojo/sort/node/provider/DorisProvider.java | 36 +++++++++
.../service/node/doris/DorisDataNodeOperator.java | 85 ++++++++++++++++++++++
.../service/sink/doris/DorisSinkOperator.java | 16 +++-
7 files changed, 292 insertions(+), 3 deletions(-)
diff --git
a/inlong-manager/manager-common/src/main/java/org/apache/inlong/manager/common/consts/DataNodeType.java
b/inlong-manager/manager-common/src/main/java/org/apache/inlong/manager/common/consts/DataNodeType.java
index e14a98195f..fda7ee7262 100644
---
a/inlong-manager/manager-common/src/main/java/org/apache/inlong/manager/common/consts/DataNodeType.java
+++
b/inlong-manager/manager-common/src/main/java/org/apache/inlong/manager/common/consts/DataNodeType.java
@@ -36,6 +36,8 @@ public class DataNodeType {
public static final String ORACLE = "ORACLE";
public static final String SQLSERVER = "SQLSERVER";
public static final String MONGODB = "MONGODB";
+ public static final String DORIS = "DORIS";
+
/**
* Tencent cloud log service
* Details: <a href="https://www.tencentcloud.com/products/cls">CLS</a>
diff --git
a/inlong-manager/manager-pojo/src/main/java/org/apache/inlong/manager/pojo/node/doris/DorisDataNodeDTO.java
b/inlong-manager/manager-pojo/src/main/java/org/apache/inlong/manager/pojo/node/doris/DorisDataNodeDTO.java
new file mode 100644
index 0000000000..fa580444a2
--- /dev/null
+++
b/inlong-manager/manager-pojo/src/main/java/org/apache/inlong/manager/pojo/node/doris/DorisDataNodeDTO.java
@@ -0,0 +1,68 @@
+/*
+ * 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.inlong.manager.pojo.node.doris;
+
+import org.apache.inlong.manager.common.enums.ErrorCodeEnum;
+import org.apache.inlong.manager.common.exceptions.BusinessException;
+import org.apache.inlong.manager.common.util.CommonBeanUtils;
+import org.apache.inlong.manager.common.util.JsonUtils;
+
+import io.swagger.annotations.ApiModel;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * Doris data node info
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@ApiModel("Doris data node info")
+public class DorisDataNodeDTO {
+
+ private static final Logger LOGGER =
LoggerFactory.getLogger(DorisDataNodeDTO.class);
+
+ /**
+ * Get the dto instance from the request
+ */
+ public static DorisDataNodeDTO getFromRequest(DorisDataNodeRequest
request, String extParams) throws Exception {
+ DorisDataNodeDTO dto = StringUtils.isNotBlank(extParams)
+ ? DorisDataNodeDTO.getFromJson(extParams)
+ : new DorisDataNodeDTO();
+ return CommonBeanUtils.copyProperties(request, dto, true);
+ }
+
+ /**
+ * Get the dto instance from the JSON string.
+ */
+ public static DorisDataNodeDTO getFromJson(@NotNull String extParams) {
+ try {
+ return JsonUtils.parseObject(extParams, DorisDataNodeDTO.class);
+ } catch (Exception e) {
+ throw new BusinessException(ErrorCodeEnum.GROUP_INFO_INCORRECT,
+ String.format("Failed to parse extParams for Doris node:
%s", e.getMessage()));
+ }
+ }
+
+}
diff --git
a/inlong-manager/manager-pojo/src/main/java/org/apache/inlong/manager/pojo/node/doris/DorisDataNodeInfo.java
b/inlong-manager/manager-pojo/src/main/java/org/apache/inlong/manager/pojo/node/doris/DorisDataNodeInfo.java
new file mode 100644
index 0000000000..99faafe882
--- /dev/null
+++
b/inlong-manager/manager-pojo/src/main/java/org/apache/inlong/manager/pojo/node/doris/DorisDataNodeInfo.java
@@ -0,0 +1,49 @@
+/*
+ * 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.inlong.manager.pojo.node.doris;
+
+import org.apache.inlong.manager.common.consts.DataNodeType;
+import org.apache.inlong.manager.common.util.CommonBeanUtils;
+import org.apache.inlong.manager.common.util.JsonTypeDefine;
+import org.apache.inlong.manager.pojo.node.DataNodeInfo;
+
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+/**
+ * Doris data node info
+ */
+@Data
+@ToString(callSuper = true)
+@EqualsAndHashCode(callSuper = true)
+@JsonTypeDefine(value = DataNodeType.DORIS)
+@ApiModel("Doris data node info")
+public class DorisDataNodeInfo extends DataNodeInfo {
+
+ public DorisDataNodeInfo() {
+ this.setType(DataNodeType.DORIS);
+ }
+
+ @Override
+ public DorisDataNodeRequest genRequest() {
+ return CommonBeanUtils.copyProperties(this, DorisDataNodeRequest::new);
+ }
+
+}
diff --git
a/inlong-manager/manager-pojo/src/main/java/org/apache/inlong/manager/pojo/node/doris/DorisDataNodeRequest.java
b/inlong-manager/manager-pojo/src/main/java/org/apache/inlong/manager/pojo/node/doris/DorisDataNodeRequest.java
new file mode 100644
index 0000000000..3416ec2e34
--- /dev/null
+++
b/inlong-manager/manager-pojo/src/main/java/org/apache/inlong/manager/pojo/node/doris/DorisDataNodeRequest.java
@@ -0,0 +1,39 @@
+/*
+ * 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.inlong.manager.pojo.node.doris;
+
+import org.apache.inlong.manager.common.consts.DataNodeType;
+import org.apache.inlong.manager.common.util.JsonTypeDefine;
+import org.apache.inlong.manager.pojo.node.DataNodeRequest;
+
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+/**
+ * Doris data node request
+ */
+@Data
+@ToString(callSuper = true)
+@EqualsAndHashCode(callSuper = true)
+@JsonTypeDefine(value = DataNodeType.DORIS)
+@ApiModel("Doris data node request")
+public class DorisDataNodeRequest extends DataNodeRequest {
+
+}
diff --git
a/inlong-manager/manager-pojo/src/main/java/org/apache/inlong/manager/pojo/sort/node/provider/DorisProvider.java
b/inlong-manager/manager-pojo/src/main/java/org/apache/inlong/manager/pojo/sort/node/provider/DorisProvider.java
index e4e71333c9..a87db38690 100644
---
a/inlong-manager/manager-pojo/src/main/java/org/apache/inlong/manager/pojo/sort/node/provider/DorisProvider.java
+++
b/inlong-manager/manager-pojo/src/main/java/org/apache/inlong/manager/pojo/sort/node/provider/DorisProvider.java
@@ -17,7 +17,9 @@
package org.apache.inlong.manager.pojo.sort.node.provider;
+import org.apache.inlong.common.enums.MetaField;
import org.apache.inlong.manager.common.consts.SinkType;
+import org.apache.inlong.manager.pojo.sink.SinkField;
import org.apache.inlong.manager.pojo.sink.doris.DorisSink;
import org.apache.inlong.manager.pojo.sort.node.base.LoadNodeProvider;
import org.apache.inlong.manager.pojo.stream.StreamField;
@@ -28,12 +30,17 @@ import org.apache.inlong.sort.protocol.node.format.Format;
import org.apache.inlong.sort.protocol.node.load.DorisLoadNode;
import org.apache.inlong.sort.protocol.transformation.FieldRelation;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
+
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* The Provider for creating Doris load nodes.
*/
+@Slf4j
public class DorisProvider implements LoadNodeProvider {
@Override
@@ -48,6 +55,7 @@ public class DorisProvider implements LoadNodeProvider {
List<FieldInfo> fieldInfos =
parseSinkFieldInfos(dorisSink.getSinkFieldList(), dorisSink.getSinkName());
List<FieldRelation> fieldRelations =
parseSinkFields(dorisSink.getSinkFieldList(), constantFieldMap);
Format format =
parsingSinkMultipleFormat(dorisSink.getSinkMultipleEnable(),
dorisSink.getSinkMultipleFormat());
+ log.info("Test sink doris pro username ={}", dorisSink);
return new DorisLoadNode(
dorisSink.getSinkName(),
@@ -68,4 +76,32 @@ public class DorisProvider implements LoadNodeProvider {
dorisSink.getDatabasePattern(),
dorisSink.getTablePattern());
}
+
+ @Override
+ public Boolean isSinkMultiple(StreamNode nodeInfo) {
+ DorisSink dorisSink = (DorisSink) nodeInfo;
+ return dorisSink.getSinkMultipleEnable();
+ }
+
+ @Override
+ public List<StreamField> addStreamFieldsForSinkMultiple(List<StreamField>
streamFields) {
+ if (CollectionUtils.isEmpty(streamFields)) {
+ streamFields = new ArrayList<>();
+ }
+ streamFields.add(0,
+ new StreamField(0, "varbinary",
MetaField.DATA_BYTES_CANAL.name(), "meta.data_canal", null, 1,
+ MetaField.DATA_BYTES_CANAL.name()));
+ return streamFields;
+ }
+
+ @Override
+ public List<SinkField> addSinkFieldsForSinkMultiple(List<SinkField>
sinkFields) {
+ if (CollectionUtils.isEmpty(sinkFields)) {
+ sinkFields = new ArrayList<>();
+ }
+ sinkFields.add(0, new SinkField(0, "varbinary",
MetaField.DATA_BYTES_CANAL.name(), "meta.data_canal",
+ MetaField.DATA_BYTES_CANAL.name(), "varbinary", 0,
MetaField.DATA_BYTES_CANAL.name(), null));
+ return sinkFields;
+ }
+
}
\ No newline at end of file
diff --git
a/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/node/doris/DorisDataNodeOperator.java
b/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/node/doris/DorisDataNodeOperator.java
new file mode 100644
index 0000000000..425f9f6592
--- /dev/null
+++
b/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/node/doris/DorisDataNodeOperator.java
@@ -0,0 +1,85 @@
+/*
+ * 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.inlong.manager.service.node.doris;
+
+import org.apache.inlong.manager.common.consts.DataNodeType;
+import org.apache.inlong.manager.common.enums.ErrorCodeEnum;
+import org.apache.inlong.manager.common.exceptions.BusinessException;
+import org.apache.inlong.manager.common.util.CommonBeanUtils;
+import org.apache.inlong.manager.dao.entity.DataNodeEntity;
+import org.apache.inlong.manager.pojo.node.DataNodeInfo;
+import org.apache.inlong.manager.pojo.node.DataNodeRequest;
+import org.apache.inlong.manager.pojo.node.doris.DorisDataNodeDTO;
+import org.apache.inlong.manager.pojo.node.doris.DorisDataNodeInfo;
+import org.apache.inlong.manager.pojo.node.doris.DorisDataNodeRequest;
+import org.apache.inlong.manager.service.node.AbstractDataNodeOperator;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class DorisDataNodeOperator extends AbstractDataNodeOperator {
+
+ private static final Logger LOGGER =
LoggerFactory.getLogger(DorisDataNodeOperator.class);
+
+ @Autowired
+ private ObjectMapper objectMapper;
+
+ @Override
+ public Boolean accept(String dataNodeType) {
+ LOGGER.info("test data type {}, actual type={}", dataNodeType,
getDataNodeType());
+ return getDataNodeType().equals(dataNodeType);
+ }
+
+ @Override
+ public String getDataNodeType() {
+ return DataNodeType.DORIS;
+ }
+
+ @Override
+ public DataNodeInfo getFromEntity(DataNodeEntity entity) {
+ if (entity == null) {
+ throw new BusinessException(ErrorCodeEnum.DATA_NODE_NOT_FOUND);
+ }
+ DorisDataNodeInfo dorisDataNodeInfo = new DorisDataNodeInfo();
+ CommonBeanUtils.copyProperties(entity, dorisDataNodeInfo);
+ if (StringUtils.isNotBlank(entity.getExtParams())) {
+ DorisDataNodeDTO dto =
DorisDataNodeDTO.getFromJson(entity.getExtParams());
+ CommonBeanUtils.copyProperties(dto, dorisDataNodeInfo);
+ }
+ return dorisDataNodeInfo;
+ }
+
+ @Override
+ protected void setTargetEntity(DataNodeRequest request, DataNodeEntity
targetEntity) {
+ DorisDataNodeRequest nodeRequest = (DorisDataNodeRequest) request;
+ CommonBeanUtils.copyProperties(nodeRequest, targetEntity, true);
+ try {
+ DorisDataNodeDTO dto =
DorisDataNodeDTO.getFromRequest(nodeRequest, targetEntity.getExtParams());
+ targetEntity.setExtParams(objectMapper.writeValueAsString(dto));
+ } catch (Exception e) {
+ throw new BusinessException(ErrorCodeEnum.SOURCE_INFO_INCORRECT,
+ String.format("Failed to build extParams for Doris node:
%s", e.getMessage()));
+ }
+ }
+
+}
diff --git
a/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/sink/doris/DorisSinkOperator.java
b/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/sink/doris/DorisSinkOperator.java
index 0ed068ac70..3c7d4c58ea 100644
---
a/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/sink/doris/DorisSinkOperator.java
+++
b/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/sink/doris/DorisSinkOperator.java
@@ -22,6 +22,7 @@ import org.apache.inlong.manager.common.enums.ErrorCodeEnum;
import org.apache.inlong.manager.common.exceptions.BusinessException;
import org.apache.inlong.manager.common.util.CommonBeanUtils;
import org.apache.inlong.manager.dao.entity.StreamSinkEntity;
+import org.apache.inlong.manager.pojo.node.doris.DorisDataNodeInfo;
import org.apache.inlong.manager.pojo.sink.SinkField;
import org.apache.inlong.manager.pojo.sink.SinkRequest;
import org.apache.inlong.manager.pojo.sink.StreamSink;
@@ -87,12 +88,21 @@ public class DorisSinkOperator extends AbstractSinkOperator
{
DorisSinkDTO dto = DorisSinkDTO.getFromJson(entity.getExtParams());
if (StringUtils.isBlank(dto.getFeNodes())) {
- throw new
BusinessException(ErrorCodeEnum.ILLEGAL_RECORD_FIELD_VALUE,
- "doris fe nodes is blank");
+ if (StringUtils.isBlank(entity.getDataNodeName())) {
+ throw new BusinessException(ErrorCodeEnum.SINK_INFO_INCORRECT,
+ "doris fe nodes unspecified and data node is blank");
+ }
+ DorisDataNodeInfo dataNodeInfo = (DorisDataNodeInfo)
dataNodeHelper.getDataNodeInfo(
+ entity.getDataNodeName(), entity.getSinkType());
+ dto.setFeNodes(dataNodeInfo.getUrl());
+ dto.setUsername(dataNodeInfo.getUsername());
+ dto.setPassword(dataNodeInfo.getToken());
+ CommonBeanUtils.copyProperties(dataNodeInfo, dto, true);
}
+
CommonBeanUtils.copyProperties(entity, sink, true);
CommonBeanUtils.copyProperties(dto, sink, true);
- List<SinkField> sinkFields = super.getSinkFields(entity.getId());
+ List<SinkField> sinkFields = getSinkFields(entity.getId());
sink.setSinkFieldList(sinkFields);
return sink;
}