Просмотр исходного кода

chore(gw): rename emqx_gateway to gateway

JianBo He 4 лет назад
Родитель
Сommit
e6a2770e2f

Разница между файлами не показана из-за своего большого размера
+ 0 - 252
apps/emqx_gateway/etc/emqx_exproto.conf


+ 1 - 3
apps/emqx_gateway/etc/emqx_gateway.conf

@@ -2,9 +2,7 @@
 ## EMQ X Gateway configurations
 ##--------------------------------------------------------------------
 
-## TODO:
-
-emqx_gateway: {
+gateway: {
 
     stomp.1: {
         frame: {

+ 0 - 364
apps/emqx_gateway/etc/priv/emqx_exproto.schema

@@ -1,364 +0,0 @@
-%% -*-: erlang -*-
-
-%%--------------------------------------------------------------------
-%% Services
-
-{mapping, "exproto.server.http.port", "emqx_exproto.servers", [
-  {datatype, integer}
-]}.
-
-{mapping, "exproto.server.https.port", "emqx_exproto.servers", [
-  {datatype, integer}
-]}.
-
-{mapping, "exproto.server.https.cacertfile", "emqx_exproto.servers", [
-  {datatype, string}
-]}.
-
-{mapping, "exproto.server.https.certfile", "emqx_exproto.servers", [
-  {datatype, string}
-]}.
-
-{mapping, "exproto.server.https.keyfile", "emqx_exproto.servers", [
-  {datatype, string}
-]}.
-
-{translation, "emqx_exproto.servers", fun(Conf) ->
-    Filter = fun(Opts) -> [{K, V} || {K, V} <- Opts, V =/= undefined] end,
-    Http = case cuttlefish:conf_get("exproto.server.http.port", Conf, undefined) of
-               undefined -> [];
-               P1 -> [{http, P1, []}]
-           end,
-    Https = case cuttlefish:conf_get("exproto.server.https.port", Conf, undefined) of
-                undefined -> [];
-                P2 ->
-                    [{https, P2,
-                        Filter([{ssl, true},
-                                {certfile, cuttlefish:conf_get("exproto.server.https.certfile", Conf)},
-                                {keyfile, cuttlefish:conf_get("exproto.server.https.keyfile", Conf)},
-                                {cacertfile, cuttlefish:conf_get("exproto.server.https.cacertfile", Conf)}])}]
-            end,
-    Http ++ Https
-end}.
-
-%%--------------------------------------------------------------------
-%% Listeners
-
-{mapping, "exproto.listener.$proto.endpoint", "emqx_exproto.listeners", [
-  {datatype, string}
-]}.
-
-{mapping, "exproto.listener.$proto.connection_handler_url", "emqx_exproto.listeners", [
-  {datatype, string}
-]}.
-
-{mapping, "exproto.listener.$proto.connection_handler_certfile", "emqx_exproto.listeners", [
-  {datatype, string}
-]}.
-
-{mapping, "exproto.listener.$proto.connection_handler_cacertfile", "emqx_exproto.listeners", [
-  {datatype, string}
-]}.
-
-{mapping, "exproto.listener.$proto.connection_handler_keyfile", "emqx_exproto.listeners", [
-  {datatype, string}
-]}.
-
-{mapping, "exproto.listener.$proto.acceptors", "emqx_exproto.listeners", [
-  {default, 8},
-  {datatype, integer}
-]}.
-
-{mapping, "exproto.listener.$proto.max_connections", "emqx_exproto.listeners", [
-  {default, 1024},
-  {datatype, integer}
-]}.
-
-{mapping, "exproto.listener.$proto.max_conn_rate", "emqx_exproto.listeners", [
-  {datatype, integer}
-]}.
-
-{mapping, "exproto.listener.$proto.active_n", "emqx_exproto.listeners", [
-  {default, 100},
-  {datatype, integer}
-]}.
-
-{mapping, "exproto.listener.$proto.idle_timeout", "emqx_exproto.listeners", [
-  {default, "30s"},
-  {datatype, {duration, ms}}
-]}.
-
-{mapping, "exproto.listener.$proto.access.$id", "emqx_exproto.listeners", [
-  {datatype, string}
-]}.
-
-{mapping, "exproto.listener.$proto.proxy_protocol", "emqx_exproto.listeners", [
-  {datatype, flag}
-]}.
-
-{mapping, "exproto.listener.$proto.proxy_protocol_timeout", "emqx_exproto.listeners", [
-  {datatype, {duration, ms}}
-]}.
-
-{mapping, "exproto.listener.$proto.backlog", "emqx_exproto.listeners", [
-  {datatype, integer},
-  {default, 1024}
-]}.
-
-{mapping, "exproto.listener.$proto.send_timeout", "emqx_exproto.listeners", [
-  {datatype, {duration, ms}},
-  {default, "15s"}
-]}.
-
-{mapping, "exproto.listener.$proto.send_timeout_close", "emqx_exproto.listeners", [
-  {datatype, flag},
-  {default, on}
-]}.
-
-{mapping, "exproto.listener.$proto.recbuf", "emqx_exproto.listeners", [
-  {datatype, bytesize},
-  hidden
-]}.
-
-{mapping, "exproto.listener.$proto.sndbuf", "emqx_exproto.listeners", [
-  {datatype, bytesize},
-  hidden
-]}.
-
-{mapping, "exproto.listener.$proto.buffer", "emqx_exproto.listeners", [
-  {datatype, bytesize},
-  hidden
-]}.
-
-{mapping, "exproto.listener.$proto.tune_buffer", "emqx_exproto.listeners", [
-  {datatype, flag},
-  hidden
-]}.
-
-{mapping, "exproto.listener.$proto.nodelay", "emqx_exproto.listeners", [
-  {datatype, {enum, [true, false]}},
-  hidden
-]}.
-
-{mapping, "exproto.listener.$proto.reuseaddr", "emqx_exproto.listeners", [
-  {datatype, {enum, [true, false]}},
-  hidden
-]}.
-
-%%--------------------------------------------------------------------
-%% TLS Options
-
-{mapping, "exproto.listener.$proto.tls_versions", "emqx_exproto.listeners", [
-  {datatype, string}
-]}.
-
-{mapping, "exproto.listener.$proto.ciphers", "emqx_exproto.listeners", [
-  {datatype, string}
-]}.
-
-{mapping, "exproto.listener.$proto.psk_ciphers", "emqx_exproto.listeners", [
-  {datatype, string}
-]}.
-
-{mapping, "exproto.listener.$proto.dhfile", "emqx_exproto.listeners", [
-  {datatype, string}
-]}.
-
-{mapping, "exproto.listener.$proto.keyfile", "emqx_exproto.listeners", [
-  {datatype, string}
-]}.
-
-{mapping, "exproto.listener.$proto.certfile", "emqx_exproto.listeners", [
-  {datatype, string}
-]}.
-
-{mapping, "exproto.listener.$proto.cacertfile", "emqx_exproto.listeners", [
-  {datatype, string}
-]}.
-
-{mapping, "exproto.listener.$proto.verify", "emqx_exproto.listeners", [
-  {datatype, atom}
-]}.
-
-{mapping, "exproto.listener.$proto.fail_if_no_peer_cert", "emqx_exproto.listeners", [
-  {datatype, {enum, [true, false]}}
-]}.
-
-{mapping, "exproto.listener.$proto.secure_renegotiate", "emqx_exproto.listeners", [
-  {datatype, flag}
-]}.
-
-{mapping, "exproto.listener.$proto.reuse_sessions", "emqx_exproto.listeners", [
-  {default, on},
-  {datatype, flag}
-]}.
-
-{mapping, "exproto.listener.$proto.honor_cipher_order", "emqx_exproto.listeners", [
-  {datatype, flag}
-]}.
-
-{translation, "emqx_exproto.listeners", fun(Conf) ->
-
-    Filter = fun(Opts) -> [{K, V} || {K, V} <- Opts, V =/= undefined] end,
-
-    Atom = fun(undefined) -> undefined; (S) -> list_to_atom(S) end,
-
-    Access = fun(S) ->
-                 [A, CIDR] = string:tokens(S, " "),
-                 {list_to_atom(A), case CIDR of "all" -> all; _ -> CIDR end}
-             end,
-
-    AccOpts = fun(Prefix) ->
-                  case cuttlefish_variable:filter_by_prefix(Prefix ++ ".access", Conf) of
-                      [] -> [];
-                      Rules -> [{access_rules, [Access(Rule) || {_, Rule} <- Rules]}]
-                  end
-              end,
-
-    RateLimit = fun(undefined) ->
-                        undefined;
-                   (Val) ->
-                        [L, D] = string:tokens(Val, ", "),
-                        Limit = case cuttlefish_bytesize:parse(L) of
-                                    Sz when is_integer(Sz) -> Sz;
-                                    {error, Reason} -> error(Reason)
-                                end,
-                        Duration = case cuttlefish_duration:parse(D, s) of
-                                       Secs when is_integer(Secs) -> Secs;
-                                       {error, Reason1} -> error(Reason1)
-                                   end,
-                        Rate = Limit / Duration,
-                        {Rate, Limit}
-                end,
-
-    HandlerOpts = fun(Prefix) ->
-                      Opts =
-                      case http_uri:parse(cuttlefish:conf_get(Prefix ++ ".connection_handler_url", Conf)) of
-                          {ok, {http, _, Host, Port, _, _}} ->
-                              [{scheme, http}, {host, Host}, {port, Port}];
-                          {ok, {https, _, Host, Port, _, _}} ->
-                              [{scheme, https}, {host, Host}, {port, Port},
-                               {ssl_options,
-                                 Filter([{certfile, cuttlefish:conf_get(Prefix ++ ".connection_handler_certfile", Conf)},
-                                         {keyfile, cuttlefish:conf_get(Prefix ++ ".connection_handler_keyfile", Conf)},
-                                         {cacertfile, cuttlefish:conf_get(Prefix ++ ".connection_handler_cacertfile", Conf)}
-                                        ])}];
-                          _ ->
-                              error(invaild_connection_handler_url)
-                      end,
-                      [{handler, Opts}]
-                  end,
-
-    ConnOpts = fun(Prefix) ->
-                   Filter([{active_n, cuttlefish:conf_get(Prefix ++ ".active_n", Conf, undefined)},
-                           {idle_timeout, cuttlefish:conf_get(Prefix ++ ".idle_timeout", Conf, undefined)}])
-               end,
-
-    LisOpts = fun(Prefix) ->
-                  Filter([{acceptors, cuttlefish:conf_get(Prefix ++ ".acceptors", Conf)},
-                          {max_connections, cuttlefish:conf_get(Prefix ++ ".max_connections", Conf)},
-                          {max_conn_rate, cuttlefish:conf_get(Prefix ++ ".max_conn_rate", Conf, undefined)},
-                          {tune_buffer, cuttlefish:conf_get(Prefix ++ ".tune_buffer", Conf, undefined)},
-                          {proxy_protocol, cuttlefish:conf_get(Prefix ++ ".proxy_protocol", Conf, undefined)},
-                          {proxy_protocol_timeout, cuttlefish:conf_get(Prefix ++ ".proxy_protocol_timeout", Conf, undefined)} | AccOpts(Prefix)])
-              end,
-
-    TcpOpts = fun(Prefix) ->
-                  Filter([{backlog, cuttlefish:conf_get(Prefix ++ ".backlog", Conf, undefined)},
-                          {send_timeout, cuttlefish:conf_get(Prefix ++ ".send_timeout", Conf, undefined)},
-                          {send_timeout_close, cuttlefish:conf_get(Prefix ++ ".send_timeout_close", Conf, undefined)},
-                          {recbuf,  cuttlefish:conf_get(Prefix ++ ".recbuf", Conf, undefined)},
-                          {sndbuf,  cuttlefish:conf_get(Prefix ++ ".sndbuf", Conf, undefined)},
-                          {buffer,  cuttlefish:conf_get(Prefix ++ ".buffer", Conf, undefined)},
-                          {nodelay, cuttlefish:conf_get(Prefix ++ ".nodelay", Conf, true)},
-                          {reuseaddr, cuttlefish:conf_get(Prefix ++ ".reuseaddr", Conf, undefined)}])
-              end,
-    SplitFun = fun(undefined) -> undefined; (S) -> string:tokens(S, ",") end,
-    MapPSKCiphers = fun(PSKCiphers) ->
-                      lists:map(
-                          fun("PSK-AES128-CBC-SHA") -> {psk, aes_128_cbc, sha};
-                             ("PSK-AES256-CBC-SHA") -> {psk, aes_256_cbc, sha};
-                             ("PSK-3DES-EDE-CBC-SHA") -> {psk, '3des_ede_cbc', sha};
-                             ("PSK-RC4-SHA") -> {psk, rc4_128, sha}
-                          end, PSKCiphers)
-                    end,
-    SslOpts = fun(Prefix) ->
-                  Versions = case SplitFun(cuttlefish:conf_get(Prefix ++ ".tls_versions", Conf, undefined)) of
-                                undefined -> undefined;
-                                L -> [list_to_atom(V) || V <- L]
-                            end,
-                  TLSCiphers = cuttlefish:conf_get(Prefix++".ciphers", Conf, undefined),
-                  PSKCiphers = cuttlefish:conf_get(Prefix++".psk_ciphers", Conf, undefined),
-                  Ciphers =
-                    case {TLSCiphers, PSKCiphers} of
-                      {undefined, undefined} ->
-                        cuttlefish:invalid(Prefix++".ciphers or "++Prefix++".psk_ciphers is absent");
-                      {TLSCiphers, undefined} ->
-                        SplitFun(TLSCiphers);
-                      {undefined, PSKCiphers} ->
-                        MapPSKCiphers(SplitFun(PSKCiphers));
-                      {_TLSCiphers, _PSKCiphers} ->
-                        cuttlefish:invalid(Prefix++".ciphers and "++Prefix++".psk_ciphers cannot be configured at the same time")
-                    end,
-                  UserLookupFun =
-                    case PSKCiphers of
-                      undefined -> undefined;
-                      _ -> {fun emqx_psk:lookup/3, <<>>}
-                    end,
-                  Filter([{versions, Versions},
-                          {ciphers, Ciphers},
-                          {user_lookup_fun, UserLookupFun},
-                          %{handshake_timeout, cuttlefish:conf_get(Prefix ++ ".handshake_timeout", Conf, undefined)},
-                          {dhfile, cuttlefish:conf_get(Prefix ++ ".dhfile", Conf, undefined)},
-                          {keyfile,    cuttlefish:conf_get(Prefix ++ ".keyfile", Conf, undefined)},
-                          {certfile,   cuttlefish:conf_get(Prefix ++ ".certfile", Conf, undefined)},
-                          {cacertfile, cuttlefish:conf_get(Prefix ++ ".cacertfile", Conf, undefined)},
-                          {verify,     cuttlefish:conf_get(Prefix ++ ".verify", Conf, undefined)},
-                          {fail_if_no_peer_cert, cuttlefish:conf_get(Prefix ++ ".fail_if_no_peer_cert", Conf, undefined)},
-                          {secure_renegotiate, cuttlefish:conf_get(Prefix ++ ".secure_renegotiate", Conf, undefined)},
-                          {reuse_sessions, cuttlefish:conf_get(Prefix ++ ".reuse_sessions", Conf, undefined)},
-                          {honor_cipher_order, cuttlefish:conf_get(Prefix ++ ".honor_cipher_order", Conf, undefined)}])
-              end,
-
-    UdpOpts = fun(Prefix) ->
-                  Filter([{recbuf,  cuttlefish:conf_get(Prefix ++ ".recbuf", Conf, undefined)},
-                          {sndbuf,  cuttlefish:conf_get(Prefix ++ ".sndbuf", Conf, undefined)},
-                          {buffer,  cuttlefish:conf_get(Prefix ++ ".buffer", Conf, undefined)},
-                          {reuseaddr, cuttlefish:conf_get(Prefix ++ ".reuseaddr", Conf, undefined)}])
-              end,
-
-    ParseListenOn = fun(ListenOn) ->
-                        case string:tokens(ListenOn, "://") of
-                            [Port] -> {tcp, list_to_integer(Port)};
-                            [T, Ip, Port]
-                              when T =:= "tcp"; T =:= "ssl";
-                                   T =:= "udp"; T =:= "dtls" ->
-                                {Atom(T), {Ip, list_to_integer(Port)}}
-                        end
-                    end,
-
-    Listeners = fun(Proto) ->
-                    Prefix = string:join(["exproto","listener", Proto], "."),
-                    Opts = HandlerOpts(Prefix) ++ ConnOpts(Prefix) ++ LisOpts(Prefix),
-                    case cuttlefish:conf_get(Prefix ++ ".endpoint", Conf, undefined) of
-                        undefined -> [];
-                        ListenOn0 ->
-                            case ParseListenOn(ListenOn0) of
-                                {tcp, ListenOn} ->
-                                    [{Proto, tcp, ListenOn, [{tcp_options, TcpOpts(Prefix)} | Opts]}];
-                                {ssl, ListenOn} ->
-                                    [{Proto, ssl, ListenOn, [{tcp_options, TcpOpts(Prefix)},
-                                                             {ssl_options, SslOpts(Prefix)} | Opts]}];
-                                {udp, ListenOn} ->
-                                    [{Proto, udp, ListenOn, [{udp_options, UdpOpts(Prefix)} | Opts]}];
-                                {dtls, ListenOn} ->
-                                    [{Proto, dtls, ListenOn, [{udp_options, UdpOpts(Prefix)},
-                                                              {dtls_options, SslOpts(Prefix)} | Opts]}];
-                                {_, _} ->
-                                    cuttlefish:invalid("Not supported listener type")
-                            end
-                    end
-                end,
-    lists:flatten([Listeners(Proto) || {[_, "listener", Proto, "endpoint"], ListenOn}
-                                   <- cuttlefish_variable:filter_by_prefix("exproto.listener", Conf)])
-end}.

+ 0 - 259
apps/emqx_gateway/etc/priv/exproto.proto

@@ -1,259 +0,0 @@
-//------------------------------------------------------------------------------
-// Copyright (c) 2020-2021 EMQ Technologies Co., Ltd. All Rights Reserved.
-//
-// Licensed 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.
-//------------------------------------------------------------------------------
-
-syntax = "proto3";
-
-package emqx.exproto.v1;
-
-// The Broker side serivce. It provides a set of APIs to
-// handle a protcol access
-service ConnectionAdapter {
-
-  // -- socket layer
-
-  rpc Send(SendBytesRequest) returns (CodeResponse) {};
-
-  rpc Close(CloseSocketRequest) returns (CodeResponse) {};
-
-  // -- protocol layer
-
-  rpc Authenticate(AuthenticateRequest) returns (CodeResponse) {};
-
-  rpc StartTimer(TimerRequest) returns (CodeResponse) {};
-
-  // -- pub/sub layer
-
-  rpc Publish(PublishRequest) returns (CodeResponse) {};
-
-  rpc Subscribe(SubscribeRequest) returns (CodeResponse) {};
-
-  rpc Unsubscribe(UnsubscribeRequest) returns (CodeResponse) {};
-}
-
-service ConnectionHandler {
-
-  // -- socket layer
-
-  rpc OnSocketCreated(stream SocketCreatedRequest) returns (EmptySuccess) {};
-
-  rpc OnSocketClosed(stream SocketClosedRequest) returns (EmptySuccess) {};
-
-  rpc OnReceivedBytes(stream ReceivedBytesRequest) returns (EmptySuccess) {};
-
-  // -- pub/sub layer
-
-  rpc OnTimerTimeout(stream TimerTimeoutRequest) returns (EmptySuccess) {};
-
-  rpc OnReceivedMessages(stream ReceivedMessagesRequest) returns (EmptySuccess) {};
-}
-
-message EmptySuccess { }
-
-enum ResultCode {
-
-  // Operation successfully
-  SUCCESS = 0;
-
-  // Unknown Error
-  UNKNOWN = 1;
-
-  // Connection process is not alive
-  CONN_PROCESS_NOT_ALIVE = 2;
-
-  // Miss the required parameter
-  REQUIRED_PARAMS_MISSED = 3;
-
-  // Params type or values incorrect
-  PARAMS_TYPE_ERROR = 4;
-
-  // No permission or Pre-conditions not fulfilled
-  PERMISSION_DENY = 5;
-}
-
-message CodeResponse {
-
-  ResultCode code = 1;
-
-  // The reason message if result is false
-  string message = 2;
-}
-
-message SendBytesRequest {
-
-  string conn = 1;
-
-  bytes bytes = 2;
-}
-
-message CloseSocketRequest {
-
-  string conn = 1;
-}
-
-message AuthenticateRequest {
-
-  string conn = 1;
-
-  ClientInfo clientinfo = 2;
-
-  string password = 3;
-}
-
-message TimerRequest {
-
-  string conn = 1;
-
-  TimerType type = 2;
-
-  uint32 interval = 3;
-}
-
-enum TimerType {
-
-  KEEPALIVE = 0;
-}
-
-message PublishRequest {
-
-  string conn = 1;
-
-  string topic = 2;
-
-  uint32 qos = 3;
-
-  bytes payload = 4;
-}
-
-message SubscribeRequest {
-
-  string conn = 1;
-
-  string topic = 2;
-
-  uint32 qos = 3;
-}
-
-message UnsubscribeRequest {
-
-  string conn = 1;
-
-  string topic = 2;
-}
-
-message SocketCreatedRequest {
-
-  string conn = 1;
-
-  ConnInfo conninfo = 2;
-}
-
-message ReceivedBytesRequest {
-
-  string conn = 1;
-
-  bytes bytes = 2;
-}
-
-message TimerTimeoutRequest {
-
-  string conn = 1;
-
-  TimerType type = 2;
-}
-
-message SocketClosedRequest {
-
-  string conn = 1;
-
-  string reason = 2;
-}
-
-message ReceivedMessagesRequest {
-
-  string conn = 1;
-
-  repeated Message messages = 2;
-}
-
-//--------------------------------------------------------------------
-// Basic data types
-//--------------------------------------------------------------------
-
-message ConnInfo {
-
-  SocketType socktype = 1;
-
-  Address peername = 2;
-
-  Address sockname = 3;
-
-  CertificateInfo peercert = 4;
-}
-
-enum SocketType {
-
-  TCP = 0;
-
-  SSL = 1;
-
-  UDP = 2;
-
-  DTLS = 3;
-}
-
-message Address {
-
-  string host = 1;
-
-  uint32 port = 2;
-}
-
-message CertificateInfo {
-
-  string cn = 1;
-
-  string dn = 2;
-}
-
-message ClientInfo {
-
-  string proto_name = 1;
-
-  string proto_ver = 2;
-
-  string clientid = 3;
-
-  string username = 4;
-
-  string mountpoint = 5;
-}
-
-message Message {
-
-  string node = 1;
-
-  string id = 2;
-
-  uint32 qos = 3;
-
-  string from = 4;
-
-  string topic = 5;
-
-  bytes  payload = 6;
-
-  uint64 timestamp = 7;
-}

+ 1 - 1
apps/emqx_gateway/src/emqx_gateway_app.erl

@@ -82,7 +82,7 @@ create_gateway_by_default([{Type, Name, Confs}|More]) ->
     create_gateway_by_default(More).
 
 zipped_confs() ->
-    All = maps:to_list(emqx_config:get([emqx_gateway])),
+    All = maps:to_list(emqx_config:get([gateway])),
     lists:append(lists:foldr(
       fun({Type, Gws}, Acc) ->
         {Names, Confs} = lists:unzip(maps:to_list(Gws)),

+ 2 - 2
apps/emqx_gateway/src/emqx_gateway_schema.erl

@@ -29,9 +29,9 @@
 -export([structs/0 , fields/1]).
 -export([t/1, t/3, t/4, ref/1]).
 
-structs() -> ["emqx_gateway"].
+structs() -> ["gateway"].
 
-fields("emqx_gateway") ->
+fields("gateway") ->
     [{stomp, t(ref(stomp))},
      {mqttsn, t(ref(mqttsn))},
      {exproto, t(ref(exproto))}

+ 1 - 1
extension_schemas.config

@@ -10,7 +10,7 @@
 , {"emqx_bridge_mqtt", emqx_bridge_mqtt_schema}
 , {"emqx_management", emqx_management_schema}
 , {"emqx_dashboard", emqx_dashboard_schema}
-, {"emqx_gateway", emqx_gateway_schema}
+, {"gateway", emqx_gateway_schema}
 , {"prometheus", emqx_prometheus_schema}
 , {"statsd", emqx_statsd_schema}
 , {"delayed", emqx_modules_schema}