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 82276c636 [INLONG-7238][Dashboard] Support cascading of redis cluster
/ data-type and format configuration (#7239)
82276c636 is described below
commit 82276c636d9b627d8b97dbbfb6305766deed747e
Author: feat <[email protected]>
AuthorDate: Wed Jan 18 01:11:04 2023 +0800
[INLONG-7238][Dashboard] Support cascading of redis cluster / data-type and
format configuration (#7239)
Co-authored-by: Charles Zhang <[email protected]>
---
inlong-dashboard/src/locales/cn.json | 34 ++-
inlong-dashboard/src/locales/en.json | 20 ++
inlong-dashboard/src/metas/sinks/defaults/Redis.ts | 326 +++++++++++++++++----
3 files changed, 311 insertions(+), 69 deletions(-)
diff --git a/inlong-dashboard/src/locales/cn.json
b/inlong-dashboard/src/locales/cn.json
index 575769d1a..5640a53cb 100644
--- a/inlong-dashboard/src/locales/cn.json
+++ b/inlong-dashboard/src/locales/cn.json
@@ -311,19 +311,39 @@
"meta.Sinks.Redis.IsMetaField": "是否为元字段",
"meta.Sinks.Redis.FieldFormat": "字段格式",
"meta.Sinks.Redis.FieldDescription": "字段描述",
- "meta.Sinks.Redis.clusterMode": "集群模式",
- "meta.Sinks.Redis.database": "DatabaseID",
- "meta.Sinks.Redis.password": "密码",
- "meta.Sinks.Redis.ttl": "TTL",
+ "meta.Sinks.Redis.ClusterMode": "集群模式",
+ "meta.Sinks.Redis.Database": "DatabaseID",
+ "meta.Sinks.Redis.Password": "密码",
+ "meta.Sinks.Redis.Ttl": "TTL",
+ "meta.Sinks.Redis.TtlUnit": "秒",
"meta.Sinks.Redis.ExtList": "高级参数",
"meta.Sinks.Redis.Timeout": "超时时间",
"meta.Sinks.Redis.SoTimeout": "读取超时时间",
"meta.Sinks.Redis.MaxTotal": "最大连接数",
"meta.Sinks.Redis.MaxIdle": "最大空闲连接数",
"meta.Sinks.Redis.MinIdle": "最小空闲连接数",
- "meta.Sinks.Redis.maxRetries": "最大重试次数",
- "meta.Sinks.Redis.dataType": "数据类型",
- "meta.Sinks.Redis.schemaMapMode": "Schema映射模式",
+ "meta.Sinks.Redis.MaxRetries": "最大重试次数",
+ "meta.Sinks.Redis.DataType": "数据类型",
+ "meta.Sinks.Redis.SchemaMapMode": "Schema 映射模式",
+ "meta.Sinks.Redis.Host": "Host",
+ "meta.Sinks.Redis.Port": "端口",
+ "meta.Sinks.Redis.SentinelMasterName": "主节点名称",
+ "meta.Sinks.Redis.SentinelsInfo": "哨兵信息",
+ "meta.Sinks.Redis.ClusterNodes": "集群节点",
+ "meta.Sinks.Redis.TimeoutUnit": "秒",
+ "meta.Sinks.Redis.SoTimeoutUnit": "秒",
+ "meta.Sinks.Redis.ClusterModeHelper": "请选择 Redis 集群模式",
+ "meta.Sinks.Redis.PortHelper": "请设置Redis服务器的端口, 默认: 6379",
+ "meta.Sinks.Redis.FormatDataType": "数据格式",
+ "meta.Sinks.Redis.FormatIgnoreParseError": "忽略数据解析错误",
+ "meta.Sinks.Redis.FormatDataEncoding": "数据编码",
+ "meta.Sinks.Redis.DataSeparator.Space": "空格",
+ "meta.Sinks.Redis.DataSeparator.VerticalLine": "竖线(|)",
+ "meta.Sinks.Redis.DataSeparator.Comma": "逗号(,)",
+ "meta.Sinks.Redis.DataSeparator.Semicolon": "分号(;)",
+ "meta.Sinks.Redis.DataSeparator.Asterisk": "星号(*)",
+ "meta.Sinks.Redis.DataSeparator.DoubleQuotes": "双引号(\")",
+ "meta.Sinks.Redis.FormatDataSeparator": "数据字段分隔符",
"meta.Group.InlongGroupId": "数据流组 ID",
"meta.Group.InlongGroupIdRules": "只能包含小写字母、数字、中划线、下划线",
"meta.Group.InlongGroupName": "数据流组名称",
diff --git a/inlong-dashboard/src/locales/en.json
b/inlong-dashboard/src/locales/en.json
index 8e8fb2046..116fbb94a 100644
--- a/inlong-dashboard/src/locales/en.json
+++ b/inlong-dashboard/src/locales/en.json
@@ -315,6 +315,7 @@
"meta.Sinks.Redis.database": "DatabaseID",
"meta.Sinks.Redis.password": "Password",
"meta.Sinks.Redis.ttl": "TTL",
+ "meta.Sinks.Redis.TtlUnit": "s",
"meta.Sinks.Redis.ExtList": "ExtList",
"meta.Sinks.Redis.Timeout": "TimeOut",
"meta.Sinks.Redis.SoTimeout": "SoTimeout",
@@ -324,6 +325,25 @@
"meta.Sinks.Redis.maxRetries": "Max Retries",
"meta.Sinks.Redis.dataType": "Data Type",
"meta.Sinks.Redis.schemaMapMode": "Schema Map Mode",
+ "meta.Sinks.Redis.Host": "Host",
+ "meta.Sinks.Redis.Port": "port",
+ "meta.Sinks.Redis.SentinelMasterName": "Sentinel Master",
+ "meta.Sinks.Redis.SentinelsInfo": "Sentinels Info",
+ "meta.Sinks.Redis.ClusterNodes": "Cluster Nodes",
+ "meta.Sinks.Redis.TimeoutUnit": "s",
+ "meta.Sinks.Redis.SoTimeoutUnit": "s",
+ "meta.Sinks.Redis.ClusterModeHelper": "Please select Cluster Mode",
+ "meta.Sinks.Redis.PortHelper": "Please select Redis server port, default:
6379",
+ "meta.Sinks.Redis.FormatDataType": "Format data type",
+ "meta.Sinks.Redis.FormatIgnoreParseError": "Ignore parse error",
+ "meta.Sinks.Redis.FormatDataEncoding": "Data encoding",
+ "meta.Sinks.Redis.DataSeparator.Space": "Space",
+ "meta.Sinks.Redis.DataSeparator.VerticalLine": "Vertical line (|)",
+ "meta.Sinks.Redis.DataSeparator.Comma": "Comma(,)",
+ "meta.Sinks.Redis.DataSeparator.Semicolon": "Semicolon(;)",
+ "meta.Sinks.Redis.DataSeparator.Asterisk": "Asterisk(*)",
+ "meta.Sinks.Redis.DataSeparator.DoubleQuotes": "Double quotes(\")",
+ "meta.Sinks.Redis.FormatDataSeparator": "Data separator",
"meta.Group.InlongGroupId": "Inlong Group ID",
"meta.Group.InlongGroupIdRules": "Only lowercase letters, numbers, minus,
and underscores",
"meta.Group.InlongGroupName": "Inlong Group Name",
diff --git a/inlong-dashboard/src/metas/sinks/defaults/Redis.ts
b/inlong-dashboard/src/metas/sinks/defaults/Redis.ts
index 1fe911331..1394170eb 100644
--- a/inlong-dashboard/src/metas/sinks/defaults/Redis.ts
+++ b/inlong-dashboard/src/metas/sinks/defaults/Redis.ts
@@ -30,26 +30,48 @@ const { FieldDecorator } = RenderRow;
const { ColumnDecorator } = RenderList;
const redisTargetTypes = [
- 'BOOLEAN',
- 'INT',
- 'BIGINT',
- 'FLOAT',
- 'DOUBLE',
- 'DATE',
- 'DATETIME',
- 'CHAR',
- 'TIME',
+ 'int',
+ 'long',
+ 'string',
+ 'float',
+ 'double',
+ 'date',
+ 'timestamp',
+ 'time',
+ 'boolean',
+ 'timestamptz',
+ 'binary',
].map(item => ({
label: item,
value: item,
}));
+const schemaMappingModeStrategies = dataType => {
+ const data = [
+ {
+ label: 'STATIC_PREFIX_MATCH',
+ value: 'STATIC_PREFIX_MATCH',
+ enable: !['BITMAP'].includes(dataType),
+ },
+ {
+ label: 'STATIC_KV_PAIR',
+ value: 'STATIC_KV_PAIR',
+ enable: !['BITMAP', 'PLAIN'].includes(dataType),
+ },
+ {
+ label: 'DYNAMIC',
+ value: 'DYNAMIC',
+ enable: !['PLAIN'].includes(dataType),
+ },
+ ];
+ return data.filter(item => item.enable);
+};
+
export default class RedisSink extends SinkInfo implements DataWithBackend,
RenderRow, RenderList {
@FieldDecorator({
type: 'select',
rules: [{ required: true }],
- initialValue: 0,
- tooltip: i18n.t('meta.Sinks.Redis.clusterModeHelp'),
+ tooltip: i18n.t('meta.Sinks.Redis.ClusterNameHelper'),
props: values => ({
disabled: [110, 130].includes(values?.status),
options: [
@@ -66,27 +88,87 @@ export default class RedisSink extends SinkInfo implements
DataWithBackend, Rend
value: 'standalone',
},
],
+ placeholder: i18n.t('meta.Sinks.Redis.ClusterModeHelper'),
}),
})
- @I18n('meta.Sinks.Redis.clusterMode')
+ @I18n('meta.Sinks.Redis.ClusterMode')
clusterMode: string;
+ @FieldDecorator({
+ type: 'input',
+ initialValue: '127.0.0.1',
+ rules: [{ required: false }],
+ props: values => ({
+ disabled: [110, 130].includes(values?.status),
+ placeholder: '127.0.0.1',
+ }),
+ visible: values => values!.clusterMode == 'standalone',
+ })
+ @ColumnDecorator()
+ @I18n('meta.Sinks.Redis.Host')
+ host: String;
+
@FieldDecorator({
type: 'inputnumber',
rules: [{ required: false }],
+ initialValue: 6379,
props: values => ({
disabled: [110, 130].includes(values?.status),
- min: 0,
+ min: 1,
+ max: 65535,
+ placeholder: i18n.t('meta.Sinks.Redis.PortHelper'),
}),
+ visible: values => values!.clusterMode == 'standalone',
})
@ColumnDecorator()
- @I18n('meta.Sinks.Redis.database')
- database: number;
+ @I18n('meta.Sinks.Redis.Port')
+ port: number;
@FieldDecorator({
- type: 'select',
+ type: 'input',
+ initialValue: '',
+ rules: [{ required: false }],
+ props: values => ({
+ disabled: [110, 130].includes(values?.status),
+ }),
+ visible: values => values!.clusterMode == 'sentinel',
+ })
+ @ColumnDecorator()
+ @I18n('meta.Sinks.Redis.SentinelMasterName')
+ sentinelMasterName: String;
+
+ @FieldDecorator({
+ type: 'input',
+ initialValue: '',
+ rules: [{ required: false }],
+ props: values => ({
+ disabled: [110, 130].includes(values?.status),
+ placeholder: '127.0.0.1:6379,127.0.0.1:6378',
+ }),
+ visible: values => values!.clusterMode == 'sentinel',
+ })
+ @ColumnDecorator()
+ @I18n('meta.Sinks.Redis.SentinelsInfo')
+ sentinelsInfo: String;
+
+ @FieldDecorator({
+ type: 'input',
+ initialValue: '',
rules: [{ required: false }],
- initialValue: 'PLAIN',
+ props: values => ({
+ disabled: [110, 130].includes(values?.status),
+ placeholder: '127.0.0.1:6379,127.0.0.1:6378',
+ }),
+ visible: values => values!.clusterMode == 'cluster',
+ })
+ @ColumnDecorator()
+ @I18n('meta.Sinks.Redis.ClusterNodes')
+ clusterNodes: String;
+
+ @FieldDecorator({
+ type: 'select',
+ rules: [{ required: true }],
+ initialValue: '',
props: values => ({
disabled: [110, 130].includes(values?.status),
options: [
@@ -106,34 +188,159 @@ export default class RedisSink extends SinkInfo
implements DataWithBackend, Rend
}),
})
@ColumnDecorator()
- @I18n('meta.Sinks.Redis.dataType')
+ @I18n('meta.Sinks.Redis.DataType')
dataType: string;
@FieldDecorator({
type: 'select',
- rules: [{ required: false }],
- initialValue: 'STATIC_PREFIX_MATCH',
+ rules: [{ required: true }],
+ props: values => ({
+ disabled: [110, 130].includes(values?.status),
+ options: schemaMappingModeStrategies(values!.dataType),
+ }),
+ })
+ @ColumnDecorator()
+ @I18n('meta.Sinks.Redis.SchemaMapMode')
+ schemaMapMode: string;
+
+ @FieldDecorator({
+ type: 'select',
+ initialValue: 'CSV',
+ visible: values => values!.schemaMapMode == 'STATIC_PREFIX_MATCH',
+ props: values => ({
+ disabled: [110, 130].includes(values?.status),
+ options: [
+ {
+ label: 'CSV',
+ value: 'CSV',
+ },
+ {
+ label: 'KV',
+ value: 'KV',
+ },
+ {
+ label: 'AVRO',
+ value: 'AVRO',
+ },
+ {
+ label: 'JSON',
+ value: 'JSON',
+ },
+ ],
+ }),
+ rules: [{ required: true }],
+ })
+ @I18n('meta.Sinks.Redis.FormatDataType')
+ formatDataType: string;
+
+ @FieldDecorator({
+ type: 'radio',
+ rules: [{ required: true }],
+ initialValue: true,
+ visible: values => values!.schemaMapMode == 'STATIC_PREFIX_MATCH',
props: values => ({
disabled: [110, 130].includes(values?.status),
options: [
{
- label: 'STATIC_PREFIX_MATCH',
- value: 'STATIC_PREFIX_MATCH',
+ label: i18n.t('basic.Yes'),
+ value: true,
},
{
- label: 'STATIC_KV_PAIR',
- value: 'STATIC_KV_PAIR',
+ label: i18n.t('basic.No'),
+ value: false,
+ },
+ ],
+ }),
+ })
+ @I18n('meta.Sinks.Redis.FormatIgnoreParseError')
+ formatIgnoreParseError: boolean;
+
+ @FieldDecorator({
+ type: 'radio',
+ initialValue: 'UTF-8',
+ visible: values => values!.schemaMapMode == 'STATIC_PREFIX_MATCH',
+ props: values => ({
+ disabled: [110, 130].includes(values?.status),
+ options: [
+ {
+ label: 'UTF-8',
+ value: 'UTF-8',
},
{
- label: 'DYNAMIC',
- value: 'DYNAMIC',
+ label: 'GBK',
+ value: 'GBK',
},
],
}),
+ rules: [{ required: true }],
+ })
+ @I18n('meta.Sinks.Redis.FormatDataEncoding')
+ formatDataEncoding: string;
+
+ @FieldDecorator({
+ type: 'select',
+ initialValue: '124',
+ visible: values => values!.schemaMapMode == 'STATIC_PREFIX_MATCH',
+ props: values => ({
+ disabled: [110, 130].includes(values?.status),
+ dropdownMatchSelectWidth: false,
+ options: [
+ {
+ label: i18n.t('meta.Sinks.Redis.DataSeparator.Space'),
+ value: '32',
+ },
+ {
+ label: i18n.t('meta.Sinks.Redis.DataSeparator.VerticalLine'),
+ value: '124',
+ },
+ {
+ label: i18n.t('meta.Sinks.Redis.DataSeparator.Comma'),
+ value: '44',
+ },
+ {
+ label: i18n.t('meta.Sinks.Redis.DataSeparator.Semicolon'),
+ value: '59',
+ },
+ {
+ label: i18n.t('meta.Sinks.Redis.DataSeparator.Asterisk'),
+ value: '42',
+ },
+ {
+ label: i18n.t('meta.Sinks.Redis.DataSeparator.DoubleQuotes'),
+ value: '34',
+ },
+ ],
+ useInput: true,
+ useInputProps: {
+ placeholder: 'ASCII',
+ },
+ style: { width: 100 },
+ }),
+ rules: [
+ {
+ required: true,
+ type: 'number',
+ transform: val => +val,
+ min: 0,
+ max: 127,
+ },
+ ],
+ })
+ @I18n('meta.Sinks.Redis.FormatDataSeparator')
+ formatDataSeparator: string;
+
+ @FieldDecorator({
+ type: 'inputnumber',
+ rules: [{ required: false }],
+ props: values => ({
+ disabled: [110, 130].includes(values?.status),
+ min: 0,
+ placholder: '0',
+ }),
})
@ColumnDecorator()
- @I18n('meta.Sinks.Redis.schemaMapMode')
- schemaMapMode: string;
+ @I18n('meta.Sinks.Redis.Database')
+ database: number;
@FieldDecorator({
type: 'password',
@@ -144,7 +351,7 @@ export default class RedisSink extends SinkInfo implements
DataWithBackend, Rend
}),
})
@ColumnDecorator()
- @I18n('meta.Sinks.Redis.password')
+ @I18n('meta.Sinks.Redis.Password')
password: string;
@FieldDecorator({
@@ -152,14 +359,24 @@ export default class RedisSink extends SinkInfo
implements DataWithBackend, Rend
initialValue: 0,
props: values => ({
disabled: [110, 130].includes(values?.status),
- min: 1,
+ min: 0,
}),
- rules: [{ required: true }],
- suffix: i18n.t('meta.Sinks.Redis.ttlUnit'),
+ rules: [{ required: false }],
+ suffix: i18n.t('meta.Sinks.Redis.TtlUnit'),
})
- @I18n('meta.Sinks.Redis.ttl')
+ @I18n('meta.Sinks.Redis.Ttl')
ttl: number;
+ @FieldDecorator({
+ type: EditableTable,
+ props: values => ({
+ size: 'small',
+ editing: ![110, 130].includes(values?.status),
+ columns: getFieldListColumns(values),
+ }),
+ })
+ sinkFieldList: Record<string, unknown>[];
+
@FieldDecorator({
type: EditableTable,
rules: [{ required: false }],
@@ -188,38 +405,36 @@ export default class RedisSink extends SinkInfo
implements DataWithBackend, Rend
@I18n('meta.Sinks.Redis.ExtList')
extList: string;
- @FieldDecorator({
- type: EditableTable,
- props: values => ({
- size: 'small',
- editing: ![110, 130].includes(values?.status),
- columns: getFieldListColumns(values),
- }),
- })
- sinkFieldList: Record<string, unknown>[];
-
@FieldDecorator({
type: 'inputnumber',
+ isPro: true,
+ initialValue: 2000,
rules: [{ required: true }],
props: values => ({
disabled: values?.status === 101,
}),
+ suffix: i18n.t('meta.Sinks.Redis.TimeoutUnit'),
})
@I18n('meta.Sinks.Redis.Timeout')
timeout: number;
@FieldDecorator({
type: 'inputnumber',
+ isPro: true,
+ initialValue: 2000,
rules: [{ required: true }],
props: values => ({
disabled: values?.status === 101,
}),
+ suffix: i18n.t('meta.Sinks.Redis.SoTimeoutUnit'),
})
@I18n('meta.Sinks.Redis.SoTimeout')
soTimeout: number;
@FieldDecorator({
type: 'inputnumber',
+ isPro: true,
+ initialValue: 2,
rules: [{ required: true }],
props: values => ({
disabled: values?.status === 101,
@@ -230,6 +445,8 @@ export default class RedisSink extends SinkInfo implements
DataWithBackend, Rend
@FieldDecorator({
type: 'inputnumber',
+ isPro: true,
+ initialValue: 8,
rules: [{ required: true }],
props: values => ({
disabled: values?.status === 101,
@@ -240,6 +457,8 @@ export default class RedisSink extends SinkInfo implements
DataWithBackend, Rend
@FieldDecorator({
type: 'inputnumber',
+ isPro: true,
+ initialValue: 1,
rules: [{ required: true }],
props: values => ({
disabled: values?.status === 101,
@@ -250,6 +469,7 @@ export default class RedisSink extends SinkInfo implements
DataWithBackend, Rend
@FieldDecorator({
type: 'inputnumber',
+ isPro: true,
rules: [{ required: true }],
initialValue: 1,
props: values => ({
@@ -257,7 +477,7 @@ export default class RedisSink extends SinkInfo implements
DataWithBackend, Rend
min: 1,
}),
})
- @I18n('meta.Sinks.Redis.maxRetries')
+ @I18n('meta.Sinks.Redis.MaxRetries')
maxRetries: number;
}
@@ -290,24 +510,6 @@ const getFieldListColumns = sinkValues => {
}),
rules: [{ required: true }],
},
- {
- title: i18n.t('meta.Sinks.Redis.IsMetaField'),
- dataIndex: 'isMetaField',
- initialValue: 0,
- type: 'select',
- props: (text, record, idx, isNew) => ({
- options: [
- {
- label: i18n.t('basic.Yes'),
- value: 1,
- },
- {
- label: i18n.t('basic.No'),
- value: 0,
- },
- ],
- }),
- },
{
title: i18n.t('meta.Sinks.Redis.FieldFormat'),
dataIndex: 'fieldFormat',