From 7fbabf5577040f6a496ac3763294ef006b8fe579 Mon Sep 17 00:00:00 2001 From: EMQ-YangM Date: Mon, 18 Apr 2022 15:13:22 +0800 Subject: [PATCH] fix: connector docs --- .../i18n/emqx_connector_api.conf | 86 +++++ .../i18n/emqx_connector_http.conf | 160 ++++++++++ .../i18n/emqx_connector_mongo.conf | 153 +++++++++ .../i18n/emqx_connector_mqtt.conf | 36 +++ .../i18n/emqx_connector_mqtt_schema.conf | 300 ++++++++++++++++++ .../i18n/emqx_connector_mysql.conf | 22 ++ .../i18n/emqx_connector_pgsql.conf | 33 ++ .../i18n/emqx_connector_redis.conf | 98 ++++++ .../i18n/emqx_connector_schema.conf | 14 + .../i18n/emqx_connector_schema_lib.conf | 69 ++++ .../emqx_connector/src/emqx_connector_api.erl | 16 +- .../src/emqx_connector_http.erl | 35 +- .../src/emqx_connector_mongo.erl | 25 +- .../src/emqx_connector_mqtt.erl | 7 +- .../src/emqx_connector_mysql.erl | 3 +- .../src/emqx_connector_pgsql.erl | 5 +- .../src/emqx_connector_redis.erl | 15 +- .../src/emqx_connector_schema.erl | 3 +- .../src/emqx_connector_schema_lib.erl | 13 +- .../src/mqtt/emqx_connector_mqtt_schema.erl | 80 ++--- 20 files changed, 1053 insertions(+), 120 deletions(-) create mode 100644 apps/emqx_connector/i18n/emqx_connector_api.conf create mode 100644 apps/emqx_connector/i18n/emqx_connector_http.conf create mode 100644 apps/emqx_connector/i18n/emqx_connector_mongo.conf create mode 100644 apps/emqx_connector/i18n/emqx_connector_mqtt.conf create mode 100644 apps/emqx_connector/i18n/emqx_connector_mqtt_schema.conf create mode 100644 apps/emqx_connector/i18n/emqx_connector_mysql.conf create mode 100644 apps/emqx_connector/i18n/emqx_connector_pgsql.conf create mode 100644 apps/emqx_connector/i18n/emqx_connector_redis.conf create mode 100644 apps/emqx_connector/i18n/emqx_connector_schema.conf create mode 100644 apps/emqx_connector/i18n/emqx_connector_schema_lib.conf diff --git a/apps/emqx_connector/i18n/emqx_connector_api.conf b/apps/emqx_connector/i18n/emqx_connector_api.conf new file mode 100644 index 000000000..f549af6cf --- /dev/null +++ b/apps/emqx_connector/i18n/emqx_connector_api.conf @@ -0,0 +1,86 @@ +emqx_connector_api { + + id { + desc { + en: "The connector ID. Must be of format {type}:{name}" + zh: "连接器 ID, 格式必须为 {type}:{name}" + } + label: { + en: "Connector ID" + zh: "连接器 ID" + } + } + + conn_test_post { + desc { + en: """ +Test creating a new connector by given ID
+The ID must be of format '{type}:{name}' +""" + zh: """ +通过给定的 ID 测试创建一个新的连接器
+ID 的格式必须为“{type}:{name}” +""" + } + label: { + en: "Create Test Connector" + zh: "创建测试连接器" + } + } + + conn_get { + desc { + en: "List all connectors" + zh: "列出所有连接器" + } + label: { + en: "List All Connectors" + zh: "列出所有连接器" + } + } + + conn_post { + desc { + en: "Create a new connector" + zh: "创建一个新的连接器" + } + label: { + en: "Create Connector" + zh: "创建连接器" + } + } + + conn_id_get { + desc { + en: "Get the connector by ID" + zh: "通过 ID 获取连接器" + } + label: { + en: "Get Connector" + zh: "获取连接器" + } + } + + conn_id_put { + desc { + en: "Update an existing connector by ID" + zh: "通过 ID 更新一个连接器" + } + label: { + en: "Update Connector" + zh: "更新连接器" + } + } + + conn_id_delete { + desc { + en: "Delete a connector by ID" + zh: "通过 ID 删除一个连接器" + } + label: { + en: "Delete Connector" + zh: "删除连接器" + } + } + +} diff --git a/apps/emqx_connector/i18n/emqx_connector_http.conf b/apps/emqx_connector/i18n/emqx_connector_http.conf new file mode 100644 index 000000000..7b06cda3a --- /dev/null +++ b/apps/emqx_connector/i18n/emqx_connector_http.conf @@ -0,0 +1,160 @@ +emqx_connector_http { + base_url { + desc { + en: """ +The base URL is the URL includes only the scheme, host and port.
+When send an HTTP request, the real URL to be used is the concatenation of the base URL and the +path parameter (passed by the emqx_resource:query/2,3 or provided by the request parameter).
+For example: `http://localhost:9901/` +""" + zh: """ +base URL 只包含host和port。
+发送HTTP请求时,真实的URL是由base URL 和 path parameter连接而成(通过emqx_resource:query/2,3传递,或者通过请求参数提供)。
+示例:`http://localhost:9901/` +""" + } + label: { + en: "Base Url" + zh: "Base Url" + } + } + + connect_timeout { + desc { + en: "The timeout when connecting to the HTTP server." + zh: "连接HTTP服务器的超时时间。" + } + label: { + en: "Connect Timeout" + zh: "连接超时" + } + } + + max_retries { + desc { + en: "Max retry times if error on sending request." + zh: "请求出错时的最大重试次数。" + } + label: { + en: "Max Retries" + zh: "最大重试次数" + } + } + + retry_interval { + desc { + en: "Interval between retries." + zh: "重试之间的间隔时间。" + } + label: { + en: "Retry Interval" + zh: "重试间隔" + } + } + + pool_type { + desc { + en: "The type of the pool. Can be one of `random`, `hash`." + zh: "连接池的类型,可用类型有`random`, `hash`。" + } + label: { + en: "Pool Type" + zh: "连接池类型" + } + } + + pool_size { + desc { + en: "The pool size." + zh: "连接池大小。" + } + label: { + en: "Pool Size" + zh: "连接池大小" + } + } + + enable_pipelining { + desc { + en: "Enable the HTTP pipeline." + zh: "允许HTTP管道。" + } + label: { + en: "HTTP Pipelineing" + zh: "HTTP管道" + } + } + + request { + desc { + en: """ +If the request is provided, the caller can send HTTP requests via +emqx_resource:query(ResourceId, {send_message, BridgeId, Message}) +""" + zh: """ +如果提供了请求,调用者可以通过以下方式发送 HTTP 请求 +emqx_resource:query(ResourceId, {send_message, BridgeId, Message}) +""" + } + label: { + en: "Request" + zh: "HTTP 请求" + } + } + + method { + desc { + en: "HTTP method." + zh: "HTTP 请求方法。" + } + label: { + en: "HTTP Method" + zh: "HTTP 请求方法" + } + } + + path { + desc { + en: "URL path." + zh: "HTTP请求路径。" + } + label: { + en: "URL Path" + zh: "HTTP请求路径" + } + } + + body { + desc { + en: "HTTP request body." + zh: "HTTP请求报文主体。" + } + label: { + en: "HTTP Body" + zh: "HTTP请求报文主体" + } + } + + headers { + desc { + en: "List of HTTP headers." + zh: "HTTP 头字段列表。" + } + label: { + en: "HTTP Headers" + zh: "HTTP 头字段列表" + } + } + + request_timeout { + desc { + en: "HTTP request timeout." + zh: "HTTP 请求超时。" + } + label: { + en: "Request Timeout" + zh: "HTTP 请求超时" + } + } + +} diff --git a/apps/emqx_connector/i18n/emqx_connector_mongo.conf b/apps/emqx_connector/i18n/emqx_connector_mongo.conf new file mode 100644 index 000000000..ba07561bb --- /dev/null +++ b/apps/emqx_connector/i18n/emqx_connector_mongo.conf @@ -0,0 +1,153 @@ +emqx_connector_mongo { + + single_mongo_type { + desc { + en: "Standalone instance." + zh: "Standalone模式。" + } + label: { + en: "Standalone instance" + zh: "Standalone模式" + } + } + + rs_mongo_type { + desc { + en: "Replica set." + zh: "Replica set模式。" + } + label: { + en: "Replica set" + zh: "Replica set模式" + } + } + + sharded_mongo_type { + desc { + en: "Sharded cluster." + zh: "Sharded cluster模式。" + } + label: { + en: "Sharded cluster" + zh: "Sharded cluster模式" + } + } + + auth_source { + desc { + en: "Database name associated with the user's credentials." + zh: "与用户证书关联的数据库名称。" + } + label: { + en: "Auth Source" + zh: "认证源" + } + } + + server { + desc { + en: """ +The IPv4 or IPv6 address or the hostname to connect to.
+A host entry has the following form: `Host[:Port]`.
+The MongoDB default port 27017 is used if `[:Port]` is not specified." +""" + zh: """ +将要连接的 IPv4 或 IPv6 地址,或者主机名。
+主机名具有以下形式:`Host[:Port]`。
+如果未指定 `[:Port]`,则使用 MongoDB 默认端口 27017。” +""" + } + label: { + en: "Server Host" + zh: "服务器地址" + } + } + + servers { + desc { + en: """ +A Node list for Cluster to connect to. The nodes should be separated with commas, such as: `Node[,Node].
` +For each Node should be: The IPv4 or IPv6 address or the hostname to connect to.
+A host entry has the following form: `Host[:Port]`.
+The MongoDB default port 27017 is used if `[:Port]` is not specified." +""" + zh: """ +集群要连接的节点列表。 节点之间用逗号分隔,如:`Node[,Node].
` +对于每个节点,应为:将要连接的 IPv4 或 IPv6 地址或主机名。
+主机条目具有以下形式:`Host[:Port]`。
+如果未指定 `[:Port]`,则使用 MongoDB 默认端口 27017。” +""" + } + label: { + en: "Servers" + zh: "服务器列表" + } + } + + w_mode { + desc { + en: "Write mode." + zh: "写模式。" + } + label: { + en: "Write Mode" + zh: "写模式" + } + } + + r_mode { + desc { + en: "Read mode." + zh: "读模式。" + } + label: { + en: "Read Mode" + zh: "读模式" + } + } + + duration { + desc { + en: "Time interval, such as timeout or TTL." + zh: "时间间隔,例如超时或 TTL。" + } + label: { + en: "Time Interval" + zh: "时间间隔" + } + } + + max_overflow { + desc { + en: "Max Overflow." + zh: "最大溢出。" + } + label: { + en: "Max Overflow" + zh: "最大溢出" + } + } + + replica_set_name { + desc { + en: "Name of the replica set." + zh: "副本集的名称。" + } + label: { + en: "Replica Set Name" + zh: "副本集名称" + } + } + + srv_record { + desc { + en: "Use DNS SRV record." + zh: "使用 DNS SRV 记录。" + } + label: { + en: "Srv Record" + zh: "SRV 记录" + } + } + +} diff --git a/apps/emqx_connector/i18n/emqx_connector_mqtt.conf b/apps/emqx_connector/i18n/emqx_connector_mqtt.conf new file mode 100644 index 000000000..1005d68dc --- /dev/null +++ b/apps/emqx_connector/i18n/emqx_connector_mqtt.conf @@ -0,0 +1,36 @@ +emqx_connector_mqtt { + + num_of_bridges { + desc { + en: "The current number of bridges that are using this connector." + zh: "当前使用此连接器的网桥数量。" + } + label: { + en: "Num of Bridges" + zh: "网桥数量" + } + } + + type { + desc { + en: "The Connector Type." + zh: "连接器类型。" + } + label: { + en: "Connector Type" + zh: "连接器类型" + } + } + + name { + desc { + en: "Connector name, used as a human-readable description of the connector." + zh: "连接器名称,人类可读的连接器描述。" + } + label: { + en: "Connector Name" + zh: "连接器名称" + } + } + +} diff --git a/apps/emqx_connector/i18n/emqx_connector_mqtt_schema.conf b/apps/emqx_connector/i18n/emqx_connector_mqtt_schema.conf new file mode 100644 index 000000000..a640625a6 --- /dev/null +++ b/apps/emqx_connector/i18n/emqx_connector_mqtt_schema.conf @@ -0,0 +1,300 @@ +emqx_connector_mqtt_schema { + mode { + desc { + en: """ +The mode of the MQTT Bridge. Can be one of 'cluster_singleton' or 'cluster_shareload'
+ +- cluster_singleton: create a unique MQTT connection within the emqx cluster.
+In 'cluster_singleton' node, all messages toward the remote broker go through the same +MQTT connection.
+- cluster_shareload: create an MQTT connection on each node in the emqx cluster.
+In 'cluster_shareload' mode, the incoming load from the remote broker is shared by +using shared subscription.
+Note that the 'clientid' is suffixed by the node name, this is to avoid +clientid conflicts between different nodes. And we can only use shared subscription +topic filters for 'remote_topic' of ingress connections. +""" + zh: """ +MQTT 桥的模式。 可用的类型有“cluster_singleton”,“cluster_shareload”。
+ +- cluster_singleton:在 emqx 集群内创建唯一的 MQTT 连接。
+在“cluster_singleton”节点中,所有发往远程代理的消息都通过相同的MQTT 连接。
+ +- cluster_shareload:在 emqx 集群的每个节点上创建一个 MQTT 连接。
+在“cluster_shareload”模式下,来自远程代理的传入负载通过共享订阅的方式接收。
+请注意,“clientid”以节点名称为后缀,这是为了避免不同节点之间的clientid冲突。 +而且对于入口连接的“remote_topic”,我们只能使用共享订阅主题过滤器。 +""" + } + label: { + en: "MQTT Bridge Mode" + zh: "MQTT 桥接模式" + } + } + + server { + desc { + en: "The host and port of the remote MQTT broker" + zh: "远程 MQTT Broker的主机和端口。" + } + label: { + en: "Broker IP And Port" + zh: "Broker主机和端口" + } + } + + proto_ver { + desc { + en: "The MQTT protocol version" + zh: "MQTT 协议版本" + } + label: { + en: "Protocol Version" + zh: "协议版本" + } + } + + username { + desc { + en: "The username of the MQTT protocol" + zh: "MQTT 协议的用户名" + } + label: { + en: "Username" + zh: "用户名" + } + } + + password { + desc { + en: "The password of the MQTT protocol" + zh: "MQTT 协议的密码" + } + label: { + en: "Password" + zh: "密码" + } + } + + clean_start { + desc { + en: "The clean-start or the clean-session of the MQTT protocol" + zh: "MQTT 清除会话" + } + label: { + en: "Clean Session" + zh: "清除会话" + } + } + + max_inflight { + desc { + en: "Max inflight (sent, but un-acked) messages of the MQTT protocol" + zh: "MQTT 协议的最大飞行(已发送但未确认)消息" + } + label: { + en: "Max Inflight Message" + zh: "最大飞行消息" + } + } + + ingress_remote_topic { + desc { + en: "Receive messages from which topic of the remote broker" + zh: "从远程broker的哪个topic接收消息" + } + label: { + en: "Remote Topic" + zh: "远程主题" + } + } + + ingress_remote_qos { + desc { + en: "The QoS level to be used when subscribing to the remote broker" + zh: "订阅远程borker时要使用的 QoS 级别" + } + label: { + en: "Remote QoS" + zh: "远程 QoS" + } + } + + ingress_local_topic { + desc { + en: """ +Send messages to which topic of the local broker.
+Template with variables is allowed. +""" + zh: """ +向本地broker的哪个topic发送消息。
+允许使用带有变量的模板。 +""" + } + label: { + en: "Local Topic" + zh: "本地主题" + } + } + + ingress_local_qos { + desc { + en: """ +The QoS of the MQTT message to be sent.
+Template with variables is allowed. +""" + zh: """ +待发送 MQTT 消息的 QoS。
+允许使用带有变量的模板。 +""" + } + label: { + en: "Local QoS" + zh: "本地 QoS" + } + } + + ingress_hookpoint { + desc { + en: "The hook point will be triggered when there's any message received from the remote broker." + zh: "当从远程borker收到任何消息时,将触发钩子。" + } + label: { + en: "Hookpoint" + zh: "挂载点" + } + } + + egress_local_topic { + desc { + en: "The local topic to be forwarded to the remote broker" + zh: "要转发到远程broker的本地主题" + } + label: { + en: "Local Topic" + zh: "本地主题" + } + } + + egress_remote_topic { + desc { + en: """ +Forward to which topic of the remote broker.
+Template with variables is allowed. +""" + zh: """ +转发到远程broker的哪个topic。
+允许使用带有变量的模板。 +""" + } + label: { + en: "Remote Topic" + zh: "远程主题" + } + } + + egress_remote_qos { + desc { + en: """ +The QoS of the MQTT message to be sent.
+Template with variables is allowed. +""" + zh: """ +待发送 MQTT 消息的 QoS。
+允许使用带有变量的模板。 +""" + } + label: { + en: "Remote QoS" + zh: "远程 QoS" + } + } + + dir { + desc { + en: """ +The dir where the replayq file saved.
+Set to 'false' disables the replayq feature. +""" + zh: """ +replayq 文件保存的目录。
+设置为 'false' 会禁用 replayq 功能。 +""" + } + label: { + en: "Replyq file Save Dir" + zh: "Replyq 文件保存目录" + } + } + + seg_bytes { + desc { + en: """ +The size in bytes of a single segment.
+A segment is mapping to a file in the replayq dir. If the current segment is full, a new segment +(file) will be opened to write. +""" + zh: """ +单个段的大小(以字节为单位)。
+一个段映射到 replayq 目录中的一个文件。 如果当前段已满,则新段(文件)将被打开写入。 +""" + } + label: { + en: "Segment Size" + zh: "Segment 大小" + } + } + + offload { + desc { + en: """ +In offload mode, the disk queue is only used to offload queue tail segments.
+The messages are cached in the memory first, then it writes to the replayq files after the size of +the memory cache reaches 'seg_bytes'. +""" + zh: """ +在Offload模式下,磁盘队列仅用于卸载队列尾段。
+消息首先缓存在内存中,然后写入replayq文件。内存缓大小为“seg_bytes” 指定的值。 +""" + } + label: { + en: "Offload Mode" + zh: "Offload 模式" + } + } + + retain { + desc { + en: """ +The 'retain' flag of the MQTT message to be sent.
+Template with variables is allowed. +""" + zh: """ +要发送的 MQTT 消息的“保留”标志。
+允许使用带有变量的模板。 +""" + } + label: { + en: "Retain Flag" + zh: "保留消息标志" + } + } + + payload { + desc { + en: """ +The payload of the MQTT message to be sent.
+Template with variables is allowed. +""" + zh: """ +要发送的 MQTT 消息的负载。
+允许使用带有变量的模板。 +""" + } + label: { + en: "Payload" + zh: "消息负载" + } + } + +} diff --git a/apps/emqx_connector/i18n/emqx_connector_mysql.conf b/apps/emqx_connector/i18n/emqx_connector_mysql.conf new file mode 100644 index 000000000..918c701c9 --- /dev/null +++ b/apps/emqx_connector/i18n/emqx_connector_mysql.conf @@ -0,0 +1,22 @@ +emqx_connector_mysql { + + server { + desc { + en: """ +The IPv4 or IPv6 address or the hostname to connect to.
+A host entry has the following form: `Host[:Port]`.
+The MySQL default port 3306 is used if `[:Port]` is not specified." +""" + zh: """ +将要连接的 IPv4 或 IPv6 地址,或者主机名。
+主机名具有以下形式:`Host[:Port]`。
+如果未指定 `[:Port]`,则使用 MySQL 默认端口 3306。” +""" + } + label: { + en: "Server Host" + zh: "服务器地址" + } + } + +} diff --git a/apps/emqx_connector/i18n/emqx_connector_pgsql.conf b/apps/emqx_connector/i18n/emqx_connector_pgsql.conf new file mode 100644 index 000000000..48010fb4a --- /dev/null +++ b/apps/emqx_connector/i18n/emqx_connector_pgsql.conf @@ -0,0 +1,33 @@ +emqx_connector_pgsql { + + server { + desc { + en: """ +The IPv4 or IPv6 address or the hostname to connect to.
+A host entry has the following form: `Host[:Port]`.
+The PostgreSQL default port 5432 is used if `[:Port]` is not specified." +""" + zh: """ +将要连接的 IPv4 或 IPv6 地址,或者主机名。
+主机名具有以下形式:`Host[:Port]`。
+如果未指定 `[:Port]`,则使用 PostgreSQL 默认端口 5432。” +""" + } + label: { + en: "Server Host" + zh: "服务器地址" + } + } + + name_queries_desc { + desc { + en: "Key-value list of SQL prepared statements." + zh: "SQL 预处理语句列表。" + } + label: { + en: "SQL Prepared Statements List" + zh: "SQL 预处理语句列表" + } + } + +} diff --git a/apps/emqx_connector/i18n/emqx_connector_redis.conf b/apps/emqx_connector/i18n/emqx_connector_redis.conf new file mode 100644 index 000000000..4da8e2885 --- /dev/null +++ b/apps/emqx_connector/i18n/emqx_connector_redis.conf @@ -0,0 +1,98 @@ +emqx_connector_redis { + + single { + desc { + en: "single mode" + zh: "单机模式。" + } + label: { + en: "Single Mode" + zh: "单机模式" + } + } + + cluster { + desc { + en: "cluster mode" + zh: "集群模式。" + } + label: { + en: "Cluster Mode" + zh: "集群模式" + } + } + + sentinel { + desc { + en: "sentinel mode" + zh: "哨兵模式。" + } + label: { + en: "Sentinel Mode" + zh: "哨兵模式" + } + } + + sentinel_desc { + desc { + en: "The cluster name in Redis sentinel mode." + zh: "Redis 哨兵模式下的集群名称。" + } + label: { + en: "Cluster Name" + zh: "集群名称" + } + } + + server { + desc { + en: """ +The IPv4 or IPv6 address or the hostname to connect to.
+A host entry has the following form: `Host[:Port]`.
+The Redis default port 6379 is used if `[:Port]` is not specified." +""" + zh: """ +将要连接的 IPv4 或 IPv6 地址,或者主机名。
+主机名具有以下形式:`Host[:Port]`。
+如果未指定 `[:Port]`,则使用 MongoDB 默认端口 27017。” +""" + } + label: { + en: "Server Host" + zh: "服务器地址" + } + } + + servers { + desc { + en: """ +A Node list for Cluster to connect to. The nodes should be separated with commas, such as: `Node[,Node].
` +For each Node should be: The IPv4 or IPv6 address or the hostname to connect to.
+A host entry has the following form: `Host[:Port]`.
+The MongoDB default port 27017 is used if `[:Port]` is not specified." +""" + zh: """ +集群要连接的节点列表。 节点之间用逗号分隔,如:`Node[,Node].
` +对于每个节点,应为:将要连接的 IPv4 或 IPv6 地址或主机名。
+主机条目具有以下形式:`Host[:Port]`。
+如果未指定 `[:Port]`,则使用 Redis 默认端口 6379。” +""" + } + label: { + en: "Servers" + zh: "服务器列表" + } + } + + database { + desc { + en: "Redis database ID." + zh: "Redis 数据库 ID。" + } + label: { + en: "Database ID" + zh: "数据库 ID" + } + } + +} diff --git a/apps/emqx_connector/i18n/emqx_connector_schema.conf b/apps/emqx_connector/i18n/emqx_connector_schema.conf new file mode 100644 index 000000000..dd3e6db37 --- /dev/null +++ b/apps/emqx_connector/i18n/emqx_connector_schema.conf @@ -0,0 +1,14 @@ +emqx_connector_schema { + + mqtt { + desc { + en: "MQTT bridges." + zh: "MQTT bridges。" + } + label: { + en: "MQTT bridges" + zh: "MQTT bridges" + } + } + +} diff --git a/apps/emqx_connector/i18n/emqx_connector_schema_lib.conf b/apps/emqx_connector/i18n/emqx_connector_schema_lib.conf new file mode 100644 index 000000000..e95524dfb --- /dev/null +++ b/apps/emqx_connector/i18n/emqx_connector_schema_lib.conf @@ -0,0 +1,69 @@ +emqx_connector_schema_lib { + + ssl { + desc { + en: "SSL connection settings." + zh: "SSL 连接设置。" + } + label: { + en: "Enable SSL" + zh: "启用SSL" + } + } + + database_desc { + desc { + en: "Database name." + zh: "数据库名字。" + } + label: { + en: "Database Name" + zh: "数据库名字" + } + } + + pool_size { + desc { + en: "Size of the connection pool." + zh: "连接池大小。" + } + label: { + en: "Pool Size" + zh: "连接池大小" + } + } + + username { + desc { + en: "EMQX's username in the external database." + zh: "内部数据库的用户名。" + } + label: { + en: "Username" + zh: "用户名" + } + } + + password { + desc { + en: "EMQX's password in the external database." + zh: "内部数据库密码。" + } + label: { + en: "Password" + zh: "密码" + } + } + + auto_reconnect { + desc { + en: "Enable automatic reconnect to the database." + zh: "自动重连数据库。" + } + label: { + en: "Auto Reconnect Database" + zh: "自动重连数据库" + } + } + +} diff --git a/apps/emqx_connector/src/emqx_connector_api.erl b/apps/emqx_connector/src/emqx_connector_api.erl index 9a043de59..c49860d49 100644 --- a/apps/emqx_connector/src/emqx_connector_api.erl +++ b/apps/emqx_connector/src/emqx_connector_api.erl @@ -21,6 +21,7 @@ -include("emqx_connector.hrl"). -include_lib("typerefl/include/types.hrl"). +-include_lib("hocon/include/hoconsc.hrl"). -import(hoconsc, [mk/2, ref/2, array/1, enum/1]). @@ -117,7 +118,7 @@ param_path_id() -> [{id, mk(binary(), #{ in => path , example => <<"mqtt:my_mqtt_connector">> - , desc => <<"The connector Id. Must be of format {type}:{name}">> + , desc => ?DESC("id") })}]. schema("/connectors_test") -> @@ -125,8 +126,7 @@ schema("/connectors_test") -> 'operationId' => '/connectors_test', post => #{ tags => [<<"connectors">>], - desc => <<"Test creating a new connector by given Id
" - "The ID must be of format '{type}:{name}'">>, + desc => ?DESC("conn_test_post"), summary => <<"Test creating connector">>, 'requestBody' => post_request_body_schema(), responses => #{ @@ -141,7 +141,7 @@ schema("/connectors") -> 'operationId' => '/connectors', get => #{ tags => [<<"connectors">>], - desc => <<"List all connectors">>, + desc => ?DESC("conn_get"), summary => <<"List connectors">>, responses => #{ 200 => emqx_dashboard_swagger:schema_with_example( @@ -151,7 +151,7 @@ schema("/connectors") -> }, post => #{ tags => [<<"connectors">>], - desc => <<"Create a new connector">>, + desc => ?DESC("conn_post"), summary => <<"Create connector">>, 'requestBody' => post_request_body_schema(), responses => #{ @@ -166,7 +166,7 @@ schema("/connectors/:id") -> 'operationId' => '/connectors/:id', get => #{ tags => [<<"connectors">>], - desc => <<"Get the connector by Id">>, + desc => ?DESC("conn_id_get"), summary => <<"Get connector">>, parameters => param_path_id(), responses => #{ @@ -177,7 +177,7 @@ schema("/connectors/:id") -> }, put => #{ tags => [<<"connectors">>], - desc => <<"Update an existing connector by Id">>, + desc => ?DESC("conn_id_put"), summary => <<"Update connector">>, parameters => param_path_id(), 'requestBody' => put_request_body_schema(), @@ -188,7 +188,7 @@ schema("/connectors/:id") -> }}, delete => #{ tags => [<<"connectors">>], - desc => <<"Delete a connector by Id">>, + desc => ?DESC("conn_id_delete"), summary => <<"Delete connector">>, parameters => param_path_id(), responses => #{ diff --git a/apps/emqx_connector/src/emqx_connector_http.erl b/apps/emqx_connector/src/emqx_connector_http.erl index f53fa17e5..641e70959 100644 --- a/apps/emqx_connector/src/emqx_connector_http.erl +++ b/apps/emqx_connector/src/emqx_connector_http.erl @@ -19,6 +19,7 @@ -include("emqx_connector.hrl"). -include_lib("typerefl/include/types.hrl"). +-include_lib("hocon/include/hoconsc.hrl"). -include_lib("emqx/include/logger.hrl"). -behaviour(emqx_resource). @@ -67,63 +68,55 @@ fields(config) -> {error, "There must be no query in the base_url"}; (_) -> ok end - , desc => " -The base URL is the URL includes only the scheme, host and port.
-When send an HTTP request, the real URL to be used is the concatenation of the base URL and the -path parameter (passed by the emqx_resource:query/2,3 or provided by the request parameter).
-For example: `http://localhost:9901/` -" + , desc => ?DESC("base_url") })} , {connect_timeout, sc(emqx_schema:duration_ms(), #{ default => "15s" - , desc => "The timeout when connecting to the HTTP server." + , desc => ?DESC("connect_timeout") })} , {max_retries, sc(non_neg_integer(), #{ default => 5 - , desc => "Max retry times if error on sending request." + , desc => ?DESC("max_retries") })} , {retry_interval, sc(emqx_schema:duration(), #{ default => "1s" - , desc => "Interval between retries." + , desc => ?DESC("retry_interval") })} , {pool_type, sc(pool_type(), #{ default => random - , desc => "The type of the pool. Can be one of `random`, `hash`." + , desc => ?DESC("pool_type") })} , {pool_size, sc(pos_integer(), #{ default => 8 - , desc => "The pool size." + , desc => ?DESC("pool_size") })} , {enable_pipelining, sc(boolean(), #{ default => true - , desc => "Enable the HTTP pipeline." + , desc => ?DESC("enable_pipelining") })} , {request, hoconsc:mk( ref("request"), #{ default => undefined , required => false - , desc => " -If the request is provided, the caller can send HTTP requests via -emqx_resource:query(ResourceId, {send_message, BridgeId, Message}) -" + , desc => ?DESC("request") })} ] ++ emqx_connector_schema_lib:ssl_fields(); fields("request") -> - [ {method, hoconsc:mk(hoconsc:enum([post, put, get, delete]), #{required => false, desc => "HTTP method."})} - , {path, hoconsc:mk(binary(), #{required => false, desc => "URL path."})} - , {body, hoconsc:mk(binary(), #{required => false, desc => "HTTP request body."})} - , {headers, hoconsc:mk(map(), #{required => false, desc => "List of HTTP headers."})} + [ {method, hoconsc:mk(hoconsc:enum([post, put, get, delete]), #{required => false, desc => ?DESC("method")})} + , {path, hoconsc:mk(binary(), #{required => false, desc => ?DESC("path")})} + , {body, hoconsc:mk(binary(), #{required => false, desc => ?DESC("body")})} + , {headers, hoconsc:mk(map(), #{required => false, desc => ?DESC("headers")})} , {request_timeout, sc(emqx_schema:duration_ms(), #{ required => false - , desc => "HTTP request timeout." + , desc => ?DESC("request_timeout") })} ]. diff --git a/apps/emqx_connector/src/emqx_connector_mongo.erl b/apps/emqx_connector/src/emqx_connector_mongo.erl index bd02ccc02..ca5143d44 100644 --- a/apps/emqx_connector/src/emqx_connector_mongo.erl +++ b/apps/emqx_connector/src/emqx_connector_mongo.erl @@ -17,6 +17,7 @@ -include("emqx_connector.hrl"). -include_lib("typerefl/include/types.hrl"). +-include_lib("hocon/include/hoconsc.hrl"). -include_lib("emqx/include/logger.hrl"). -include_lib("snabbkaffe/include/snabbkaffe.hrl"). @@ -55,14 +56,14 @@ roots() -> fields(single) -> [ {mongo_type, #{type => single, default => single, - desc => "Standalone instance."}} + desc => ?DESC("single_mongo_type")}} , {server, fun server/1} , {w_mode, fun w_mode/1} ] ++ mongo_fields(); fields(rs) -> [ {mongo_type, #{type => rs, default => rs, - desc => "Replica set."}} + desc => ?DESC("rs_mongo_type")}} , {servers, fun servers/1} , {w_mode, fun w_mode/1} , {r_mode, fun r_mode/1} @@ -71,7 +72,7 @@ fields(rs) -> fields(sharded) -> [ {mongo_type, #{type => sharded, default => sharded, - desc => "Sharded cluster."}} + desc => ?DESC("sharded_mongo_type")}} , {servers, fun servers/1} , {w_mode, fun w_mode/1} ] ++ mongo_fields(); @@ -107,7 +108,7 @@ mongo_fields() -> , {password, fun emqx_connector_schema_lib:password/1} , {auth_source, #{ type => binary() , required => false - , desc => "Database name associated with the user's credentials." + , desc => ?DESC("auth_source") }} , {database, fun emqx_connector_schema_lib:database/1} , {topology, #{type => hoconsc:ref(?MODULE, topology), required => false}} @@ -303,43 +304,43 @@ server(type) -> emqx_schema:ip_port(); server(required) -> true; server(validator) -> [?NOT_EMPTY("the value of the field 'server' cannot be empty")]; server(converter) -> fun to_server_raw/1; -server(desc) -> ?SERVER_DESC("MongoDB", integer_to_list(?MONGO_DEFAULT_PORT)); +server(desc) -> ?DESC("server"); server(_) -> undefined. servers(type) -> list(); servers(required) -> true; servers(validator) -> [?NOT_EMPTY("the value of the field 'servers' cannot be empty")]; servers(converter) -> fun to_servers_raw/1; -servers(desc) -> ?SERVERS_DESC ++ server(desc); +servers(desc) -> ?DESC("servers"); servers(_) -> undefined. w_mode(type) -> hoconsc:enum([unsafe, safe]); -w_mode(desc) -> "Write mode."; +w_mode(desc) -> ?DESC("w_mode"); w_mode(default) -> unsafe; w_mode(_) -> undefined. r_mode(type) -> hoconsc:enum([master, slave_ok]); -r_mode(desc) -> "Read mode."; +r_mode(desc) -> ?DESC("r_mode"); r_mode(default) -> master; r_mode(_) -> undefined. duration(type) -> emqx_schema:duration_ms(); -duration(desc) -> "Time interval, such as timeout or TTL."; +duration(desc) -> ?DESC("duration"); duration(required) -> false; duration(_) -> undefined. max_overflow(type) -> non_neg_integer(); -max_overflow(desc) -> "Max Overflow."; +max_overflow(desc) -> ?DESC("max_overflow"); max_overflow(default) -> 0; max_overflow(_) -> undefined. replica_set_name(type) -> binary(); -replica_set_name(desc) -> "Name of the replica set."; +replica_set_name(desc) -> ?DESC("replica_set_name"); replica_set_name(required) -> false; replica_set_name(_) -> undefined. srv_record(type) -> boolean(); -srv_record(desc) -> "Use DNS SRV record."; +srv_record(desc) -> ?DESC("srv_record"); srv_record(default) -> false; srv_record(_) -> undefined. diff --git a/apps/emqx_connector/src/emqx_connector_mqtt.erl b/apps/emqx_connector/src/emqx_connector_mqtt.erl index 24c0de653..60484b018 100644 --- a/apps/emqx_connector/src/emqx_connector_mqtt.erl +++ b/apps/emqx_connector/src/emqx_connector_mqtt.erl @@ -16,6 +16,7 @@ -module(emqx_connector_mqtt). -include_lib("typerefl/include/types.hrl"). +-include_lib("hocon/include/hoconsc.hrl"). -include_lib("emqx/include/logger.hrl"). -behaviour(supervisor). @@ -55,7 +56,7 @@ fields("config") -> fields("get") -> [ {num_of_bridges, mk(integer(), - #{ desc => "The current number of bridges that are using this connector" + #{ desc => ?DESC("num_of_bridges") })} ] ++ fields("post"); @@ -65,11 +66,11 @@ fields("put") -> fields("post") -> [ {type, mk(mqtt, #{ required => true - , desc => "The Connector Type" + , desc => ?DESC("type") })} , {name, mk(binary(), #{ required => true - , desc => "Connector name, used as a human-readable description of the connector." + , desc => ?DESC("name") })} ] ++ fields("put"). diff --git a/apps/emqx_connector/src/emqx_connector_mysql.erl b/apps/emqx_connector/src/emqx_connector_mysql.erl index 2e939760c..e82999ba7 100644 --- a/apps/emqx_connector/src/emqx_connector_mysql.erl +++ b/apps/emqx_connector/src/emqx_connector_mysql.erl @@ -17,6 +17,7 @@ -include("emqx_connector.hrl"). -include_lib("typerefl/include/types.hrl"). +-include_lib("hocon/include/hoconsc.hrl"). -include_lib("emqx/include/logger.hrl"). -behaviour(emqx_resource). @@ -53,7 +54,7 @@ server(type) -> emqx_schema:ip_port(); server(required) -> true; server(validator) -> [?NOT_EMPTY("the value of the field 'server' cannot be empty")]; server(converter) -> fun to_server/1; -server(desc) -> ?SERVER_DESC("MySQL", integer_to_list(?MYSQL_DEFAULT_PORT)); +server(desc) -> ?DESC("server"); server(_) -> undefined. %% =================================================================== diff --git a/apps/emqx_connector/src/emqx_connector_pgsql.erl b/apps/emqx_connector/src/emqx_connector_pgsql.erl index 36d760e15..513640e86 100644 --- a/apps/emqx_connector/src/emqx_connector_pgsql.erl +++ b/apps/emqx_connector/src/emqx_connector_pgsql.erl @@ -18,6 +18,7 @@ -include("emqx_connector.hrl"). -include_lib("typerefl/include/types.hrl"). -include_lib("emqx/include/logger.hrl"). +-include_lib("hocon/include/hoconsc.hrl"). -include_lib("epgsql/include/epgsql.hrl"). -export([roots/0, fields/1]). @@ -56,7 +57,7 @@ fields(config) -> emqx_connector_schema_lib:ssl_fields(). named_queries(type) -> map(); -named_queries(desc) -> "Key-value list of prepared SQL statements."; +named_queries(desc) -> ?DESC("name_queries_desc"); named_queries(required) -> false; named_queries(_) -> undefined. @@ -64,7 +65,7 @@ server(type) -> emqx_schema:ip_port(); server(required) -> true; server(validator) -> [?NOT_EMPTY("the value of the field 'server' cannot be empty")]; server(converter) -> fun to_server/1; -server(desc) -> ?SERVER_DESC("PostgreSQL", integer_to_list(?PGSQL_DEFAULT_PORT)); +server(desc) -> ?DESC("server"); server(_) -> undefined. %% =================================================================== diff --git a/apps/emqx_connector/src/emqx_connector_redis.erl b/apps/emqx_connector/src/emqx_connector_redis.erl index fe07bbd21..77180391c 100644 --- a/apps/emqx_connector/src/emqx_connector_redis.erl +++ b/apps/emqx_connector/src/emqx_connector_redis.erl @@ -17,6 +17,7 @@ -include("emqx_connector.hrl"). -include_lib("typerefl/include/types.hrl"). +-include_lib("hocon/include/hoconsc.hrl"). -include_lib("emqx/include/logger.hrl"). -export([roots/0, fields/1]). @@ -56,7 +57,7 @@ fields(single) -> [ {server, fun server/1} , {redis_type, #{type => hoconsc:enum([single]), default => single, - desc => "Redis type." + desc => ?DESC("single") }} ] ++ redis_fields() ++ @@ -65,7 +66,7 @@ fields(cluster) -> [ {servers, fun servers/1} , {redis_type, #{type => hoconsc:enum([cluster]), default => cluster, - desc => "Redis type." + desc => ?DESC("cluster") }} ] ++ redis_fields() ++ @@ -74,9 +75,9 @@ fields(sentinel) -> [ {servers, fun servers/1} , {redis_type, #{type => hoconsc:enum([sentinel]), default => sentinel, - desc => "Redis type." + desc => ?DESC("sentinel") }} - , {sentinel, #{type => string(), desc => "The cluster name in Redis sentinel mode." + , {sentinel, #{type => string(), desc => ?DESC("sentinel_desc") }} ] ++ redis_fields() ++ @@ -86,14 +87,14 @@ server(type) -> emqx_schema:ip_port(); server(required) -> true; server(validator) -> [?NOT_EMPTY("the value of the field 'server' cannot be empty")]; server(converter) -> fun to_server_raw/1; -server(desc) -> ?SERVER_DESC("Redis", integer_to_list(?REDIS_DEFAULT_PORT)); +server(desc) -> ?DESC("server"); server(_) -> undefined. servers(type) -> list(); servers(required) -> true; servers(validator) -> [?NOT_EMPTY("the value of the field 'servers' cannot be empty")]; servers(converter) -> fun to_servers_raw/1; -servers(desc) -> ?SERVERS_DESC ++ server(desc); +servers(desc) -> ?DESC("servers"); servers(_) -> undefined. %% =================================================================== @@ -209,7 +210,7 @@ redis_fields() -> , {password, fun emqx_connector_schema_lib:password/1} , {database, #{type => integer(), default => 0, - desc => "Redis database ID." + desc => ?DESC("database") }} , {auto_reconnect, fun emqx_connector_schema_lib:auto_reconnect/1} ]. diff --git a/apps/emqx_connector/src/emqx_connector_schema.erl b/apps/emqx_connector/src/emqx_connector_schema.erl index 5cd7d7a2a..25f846e45 100644 --- a/apps/emqx_connector/src/emqx_connector_schema.erl +++ b/apps/emqx_connector/src/emqx_connector_schema.erl @@ -18,6 +18,7 @@ -behaviour(hocon_schema). -include_lib("typerefl/include/types.hrl"). +-include_lib("hocon/include/hoconsc.hrl"). -import(hoconsc, [mk/2, ref/2]). @@ -58,7 +59,7 @@ fields("connectors") -> mk(hoconsc:map(name, hoconsc:union([ ref(emqx_connector_mqtt_schema, "connector") ])), - #{ desc => "MQTT bridges" + #{ desc => ?DESC("mqtt") })} ]. diff --git a/apps/emqx_connector/src/emqx_connector_schema_lib.erl b/apps/emqx_connector/src/emqx_connector_schema_lib.erl index 53fae8d31..c20320a36 100644 --- a/apps/emqx_connector/src/emqx_connector_schema_lib.erl +++ b/apps/emqx_connector/src/emqx_connector_schema_lib.erl @@ -17,6 +17,7 @@ -include("emqx_connector.hrl"). -include_lib("typerefl/include/types.hrl"). +-include_lib("hocon/include/hoconsc.hrl"). -export([ relational_db_fields/0 , ssl_fields/0 @@ -53,7 +54,7 @@ fields(_) -> []. ssl_fields() -> [ {ssl, #{type => hoconsc:ref(emqx_schema, ssl_client_opts), default => #{<<"enable">> => false}, - desc => "SSL connection settings." + desc => ?DESC("ssl") } } ]. @@ -67,29 +68,29 @@ relational_db_fields() -> ]. database(type) -> binary(); -database(desc) -> "Database name."; +database(desc) -> ?DESC("database_desc"); database(required) -> true; database(validator) -> [?NOT_EMPTY("the value of the field 'database' cannot be empty")]; database(_) -> undefined. pool_size(type) -> pos_integer(); -pool_size(desc) -> "Size of the connection pool."; +pool_size(desc) -> ?DESC("pool_size"); pool_size(default) -> 8; pool_size(validator) -> [?MIN(1)]; pool_size(_) -> undefined. username(type) -> binary(); -username(desc) -> "EMQX's username in the external database."; +username(desc) -> ?DESC("username"); username(required) -> false; username(_) -> undefined. password(type) -> binary(); -password(desc) -> "EMQX's password in the external database."; +password(desc) -> ?DESC("password"); password(required) -> false; password(_) -> undefined. auto_reconnect(type) -> boolean(); -auto_reconnect(desc) -> "Enable automatic reconnect to the database."; +auto_reconnect(desc) -> ?DESC("auto_reconnect"); auto_reconnect(default) -> true; auto_reconnect(_) -> undefined. diff --git a/apps/emqx_connector/src/mqtt/emqx_connector_mqtt_schema.erl b/apps/emqx_connector/src/mqtt/emqx_connector_mqtt_schema.erl index 25291059d..2e512f14e 100644 --- a/apps/emqx_connector/src/mqtt/emqx_connector_mqtt_schema.erl +++ b/apps/emqx_connector/src/mqtt/emqx_connector_mqtt_schema.erl @@ -17,6 +17,7 @@ -module(emqx_connector_mqtt_schema). -include_lib("typerefl/include/types.hrl"). +-include_lib("hocon/include/hoconsc.hrl"). -behaviour(hocon_schema). @@ -44,24 +45,12 @@ fields("connector") -> [ {mode, sc(hoconsc:enum([cluster_shareload]), #{ default => cluster_shareload - , desc => " -The mode of the MQTT Bridge. Can be one of 'cluster_singleton' or 'cluster_shareload'
- -- cluster_singleton: create a unique MQTT connection within the emqx cluster.
-In 'cluster_singleton' node, all messages toward the remote broker go through the same -MQTT connection.
-- cluster_shareload: create an MQTT connection on each node in the emqx cluster.
-In 'cluster_shareload' mode, the incoming load from the remote broker is shared by -using shared subscription.
-Note that the 'clientid' is suffixed by the node name, this is to avoid -clientid conflicts between different nodes. And we can only use shared subscription -topic filters for 'remote_topic' of ingress connections. -" + , desc => ?DESC("mode") })} , {server, sc(emqx_schema:ip_port(), #{ default => "127.0.0.1:1883" - , desc => "The host and port of the remote MQTT broker" + , desc => ?DESC("server") })} , {reconnect_interval, mk_duration( "Reconnect interval. Delay for the MQTT bridge to retry establishing the connection " @@ -70,22 +59,22 @@ topic filters for 'remote_topic' of ingress connections. , {proto_ver, sc(hoconsc:enum([v3, v4, v5]), #{ default => v4 - , desc => "The MQTT protocol version" + , desc => ?DESC("proto_ver") })} , {username, sc(binary(), #{ default => "emqx" - , desc => "The username of the MQTT protocol" + , desc => ?DESC("username") })} , {password, sc(binary(), #{ default => "emqx" - , desc => "The password of the MQTT protocol" + , desc => ?DESC("password") })} , {clean_start, sc(boolean(), #{ default => true - , desc => "The clean-start or the clean-session of the MQTT protocol" + , desc => ?DESC("clean_start") })} , {keepalive, mk_duration("MQTT Keepalive.", #{default => "300s"})} , {retry_interval, mk_duration( @@ -95,7 +84,7 @@ topic filters for 'remote_topic' of ingress connections. , {max_inflight, sc(non_neg_integer(), #{ default => 32 - , desc => "Max inflight (sent, but un-acked) messages of the MQTT protocol" + , desc => ?DESC("max_inflight") })} , {replayq, sc(ref("replayq"), #{})} @@ -107,33 +96,26 @@ fields("ingress") -> sc(binary(), #{ required => true , validator => fun ?MODULE:non_empty_string/1 - , desc => "Receive messages from which topic of the remote broker" + , desc => ?DESC("ingress_remote_topic") })} , {remote_qos, sc(qos(), #{ default => 1 - , desc => "The QoS level to be used when subscribing to the remote broker" + , desc => ?DESC("ingress_remote_qos") })} , {local_topic, sc(binary(), #{ validator => fun ?MODULE:non_empty_string/1 - , desc => " -Send messages to which topic of the local broker.
-Template with variables is allowed. -" + , desc => ?DESC("ingress_local_topic") })} , {local_qos, sc(qos(), #{ default => <<"${qos}">> - , desc => " -The QoS of the MQTT message to be sent.
-Template with variables is allowed." + , desc => ?DESC("ingress_local_qos") })} , {hookpoint, sc(binary(), - #{ desc => " -The hook point will be triggered when there's any message received from the remote broker. -" + #{ desc => ?DESC("ingress_hookpoint") })} ] ++ common_inout_confs(); @@ -141,52 +123,36 @@ fields("egress") -> %% the message maybe sent from rules, in this case 'local_topic' is not necessary [ {local_topic, sc(binary(), - #{ desc => "The local topic to be forwarded to the remote broker" + #{ desc => ?DESC("egress_local_topic") , validator => fun ?MODULE:non_empty_string/1 })} , {remote_topic, sc(binary(), #{ default => <<"${topic}">> , validator => fun ?MODULE:non_empty_string/1 - , desc => " -Forward to which topic of the remote broker.
-Template with variables is allowed. -" + , desc => ?DESC("egress_remote_topic") })} , {remote_qos, sc(qos(), #{ default => <<"${qos}">> - , desc => " -The QoS of the MQTT message to be sent.
-Template with variables is allowed." + , desc => ?DESC("egress_remote_qos") })} ] ++ common_inout_confs(); fields("replayq") -> [ {dir, sc(hoconsc:union([boolean(), string()]), - #{ desc => " -The dir where the replayq file saved.
-Set to 'false' disables the replayq feature. -" + #{ desc => ?DESC("dir") })} , {seg_bytes, sc(emqx_schema:bytesize(), #{ default => "100MB" - , desc => " -The size in bytes of a single segment.
-A segment is mapping to a file in the replayq dir. If the current segment is full, a new segment -(file) will be opened to write. -" + , desc => ?DESC("seg_bytes") })} , {offload, sc(boolean(), #{ default => false - , desc => " -In offload mode, the disk queue is only used to offload queue tail segments.
-The messages are cached in the memory first, then it writes to the replayq files after the size of -the memory cache reaches 'seg_bytes'. -" + , desc => ?DESC("offload") })} ]. @@ -235,16 +201,12 @@ common_inout_confs() -> [ {retain, sc(hoconsc:union([boolean(), binary()]), #{ default => <<"${retain}">> - , desc => " -The 'retain' flag of the MQTT message to be sent.
-Template with variables is allowed." + , desc => ?DESC("retain") })} , {payload, sc(binary(), #{ default => <<"${payload}">> - , desc => " -The payload of the MQTT message to be sent.
-Template with variables is allowed." + , desc => ?DESC("payload") })} ].