From cc0c9414aed98c0bf2930da424b8c8047df276ec Mon Sep 17 00:00:00 2001 From: Lizhen <88174078+bluewang@users.noreply.github.com> Date: Fri, 2 Feb 2024 22:47:22 +0800 Subject: [PATCH] [INLONG-9663][Dashboard] Data synchronization doris sink supports append Mode (#9665) --- .../plugins/sinks/common/SinkDefaultInfo.ts | 2 +- .../src/plugins/sinks/defaults/Doris.ts | 83 +++++++++++++++++-- inlong-dashboard/src/ui/locales/cn.json | 6 ++ inlong-dashboard/src/ui/locales/en.json | 6 ++ .../SynchronizeDetail/SyncSink/helper.ts | 4 +- 5 files changed, 89 insertions(+), 12 deletions(-) diff --git a/inlong-dashboard/src/plugins/sinks/common/SinkDefaultInfo.ts b/inlong-dashboard/src/plugins/sinks/common/SinkDefaultInfo.ts index 381da1a309c..7ec7fb87980 100644 --- a/inlong-dashboard/src/plugins/sinks/common/SinkDefaultInfo.ts +++ b/inlong-dashboard/src/plugins/sinks/common/SinkDefaultInfo.ts @@ -201,7 +201,7 @@ export class SinkDefaultInfo implements DataWithBackend, RenderRow, RenderList { disabled: Boolean(values.id), dropdownMatchSelectWidth: false, options: sinks - .filter(item => item.value === 'ICEBERG') + .filter(item => item.value === 'ICEBERG' || item.value === 'DORIS') .map(item => ({ label: item.label, value: item.value, diff --git a/inlong-dashboard/src/plugins/sinks/defaults/Doris.ts b/inlong-dashboard/src/plugins/sinks/defaults/Doris.ts index 2f0d5362c1d..c4f2d164a44 100644 --- a/inlong-dashboard/src/plugins/sinks/defaults/Doris.ts +++ b/inlong-dashboard/src/plugins/sinks/defaults/Doris.ts @@ -24,9 +24,10 @@ import i18n from '@/i18n'; import EditableTable from '@/ui/components/EditableTable'; import { SinkInfo } from '../common/SinkInfo'; import { sourceFields } from '../common/sourceFields'; +import NodeSelect from '@/ui/components/NodeSelect'; const { I18n } = DataWithBackend; -const { FieldDecorator, SyncField, IngestionField } = RenderRow; +const { FieldDecorator, SyncField, IngestionField, SyncMoveDbField } = RenderRow; const { ColumnDecorator } = RenderList; const dorisTargetTypes = [ @@ -64,31 +65,95 @@ export default class DorisSink extends SinkInfo implements DataWithBackend, Rend @I18n('meta.Sinks.Doris.HttpAddress') @SyncField() @IngestionField() + @SyncMoveDbField() feNodes: string; @FieldDecorator({ - type: 'input', + type: NodeSelect, rules: [{ required: true }], props: values => ({ disabled: [110].includes(values?.status), + nodeType: 'DORIS', }), }) - @I18n('meta.Sinks.Username') + @I18n('meta.Sinks.DataNodeName') @SyncField() @IngestionField() - username: string; + @SyncMoveDbField() + dataNodeName: string; @FieldDecorator({ - type: 'password', + type: 'radiobutton', + initialValue: '${database}', + tooltip: i18n.t('meta.Sinks.Doris.PatternHelp'), rules: [{ required: true }], props: values => ({ + size: 'middle', disabled: [110].includes(values?.status), + options: [ + { + label: i18n.t('meta.Sinks.Doris.Options.DBSameName'), + value: '${database}', + disabled: Boolean(values.id), + }, + { + label: i18n.t('meta.Sinks.Doris.Options.Customize'), + value: 'false', + disabled: Boolean(values.id), + }, + ], }), + suffix: { + type: 'input', + name: 'databasePattern', + visible: values => + values.backupDatabase === 'false' || + (values.id !== undefined && values.databasePattern !== '${database}'), + props: values => ({ + style: { width: 100 }, + disabled: [110].includes(values?.status), + }), + }, }) - @I18n('meta.Sinks.Password') - @SyncField() - @IngestionField() - password: string; + @SyncMoveDbField() + @I18n('meta.Sinks.Doris.DatabaseNamePattern') + backupDatabase: string; + + @FieldDecorator({ + type: 'radiobutton', + initialValue: '${table}', + rules: [{ required: true }], + tooltip: i18n.t('meta.Sinks.Doris.PatternHelp'), + props: values => ({ + size: 'middle', + options: [ + { + label: i18n.t('meta.Sinks.Doris.Options.TableSameName'), + value: '${table}', + disabled: Boolean(values.id), + }, + { + label: i18n.t('meta.Sinks.Doris.Options.Customize'), + value: 'false', + disabled: Boolean(values.id), + }, + ], + }), + suffix: { + type: 'input', + name: 'tablePattern', + visible: values => + values.backupTable === 'false' || + (values.id !== undefined && values.tablePattern !== '${table}'), + props: values => ({ + style: { width: 100 }, + disabled: [110].includes(values?.status), + }), + }, + }) + @SyncMoveDbField() + @I18n('meta.Sinks.Doris.TableNamePattern') + backupTable: string; @FieldDecorator({ type: 'input', diff --git a/inlong-dashboard/src/ui/locales/cn.json b/inlong-dashboard/src/ui/locales/cn.json index 99cabbacae1..c37d240a779 100644 --- a/inlong-dashboard/src/ui/locales/cn.json +++ b/inlong-dashboard/src/ui/locales/cn.json @@ -273,6 +273,12 @@ "meta.Sinks.Doris.TablePattern": "多表模式", "meta.Sinks.Doris.IsMetaField": "是否为元字段", "meta.Sinks.Doris.FieldFormat": "字段格式", + "meta.Sinks.Doris.DatabaseNamePattern": "库匹配策略", + "meta.Sinks.Doris.TableNamePattern": "表匹配策略", + "meta.Sinks.Doris.PatternHelp": "自定义配置说明:内置参数包括:1、来源库名:${database} 2、来源表名:${table} 【使用说明】:支持使用内置参数和字符串组合生成目标库表名称【示例】:如来源表名称为 table1,映射规则为 ${table}_inlong,则table1的数据将被最终映射写入至 table1_inlong 中。", + "meta.Sinks.Doris.Options.DBSameName": "与来源库同名", + "meta.Sinks.Doris.Options.TableSameName": "与来源表同名", + "meta.Sinks.Doris.Options.Customize": "自定义", "meta.Sinks.HBase.Namespace": "命名空间", "meta.Sinks.HBase.TableName": "表名称", "meta.Sinks.HBase.RowKey": "RowKey", diff --git a/inlong-dashboard/src/ui/locales/en.json b/inlong-dashboard/src/ui/locales/en.json index 3d1ecce05c7..a7140354447 100644 --- a/inlong-dashboard/src/ui/locales/en.json +++ b/inlong-dashboard/src/ui/locales/en.json @@ -273,6 +273,12 @@ "meta.Sinks.Doris.TablePattern": "Table pattern", "meta.Sinks.Doris.IsMetaField": "Is meta field", "meta.Sinks.Doris.FieldFormat": "Field format", + "meta.Sinks.Doris.DatabaseNamePattern": "Database name pattern", + "meta.Sinks.Doris.TableNamePattern": "Table name pattern", + "meta.Sinks.Doris.PatternHelp": "Custom configuration instructions: Built-in parameters include: 1. Source database name: ${database} 2. Source table name: ${table} [Usage Instructions]: Supports the use of built-in parameters and string combinations to generate target database table names [Example] : If the source table name is table1 and the mapping rule is ${table}_inlong, the data of table1 will be finally mapped and written to table1_inlong.", + "meta.Sinks.Doris.Options.DBSameName": "Same as source database", + "meta.Sinks.Doris.Options.TableSameName": "Same as source table", + "meta.Sinks.Doris.Options.Customize": "Customize", "meta.Sinks.HBase.Namespace": "Namespace", "meta.Sinks.HBase.TableName": "Table name", "meta.Sinks.HBase.RowKey": "Row key", diff --git a/inlong-dashboard/src/ui/pages/SynchronizeDetail/SyncSink/helper.ts b/inlong-dashboard/src/ui/pages/SynchronizeDetail/SyncSink/helper.ts index 5421816eb24..c66eb9333b9 100644 --- a/inlong-dashboard/src/ui/pages/SynchronizeDetail/SyncSink/helper.ts +++ b/inlong-dashboard/src/ui/pages/SynchronizeDetail/SyncSink/helper.ts @@ -19,7 +19,7 @@ export const paramReplace = (sinkType, values) => { const replaceValues = values; - if (sinkType === 'ICEBERG') { + if (sinkType === 'ICEBERG' || sinkType === 'DORIS') { if (values.backupDatabase === '${database}') { replaceValues.databasePattern = values.backupDatabase; } @@ -35,7 +35,7 @@ export const paramReplace = (sinkType, values) => { export const dataToForm = (sinkType, data) => { const sinkData = data; - if (sinkType === 'ICEBERG') { + if (sinkType === 'ICEBERG' || sinkType === 'DORIS') { if (data.databasePattern !== '${database}') { sinkData.backupDatabase = 'false'; }