diff --git a/.ci/docker-compose-file/docker-compose-greptimedb.yaml b/.ci/docker-compose-file/docker-compose-greptimedb.yaml index 8980c946d..6813b4983 100644 --- a/.ci/docker-compose-file/docker-compose-greptimedb.yaml +++ b/.ci/docker-compose-file/docker-compose-greptimedb.yaml @@ -4,7 +4,7 @@ services: greptimedb: container_name: greptimedb hostname: greptimedb - image: greptime/greptimedb:0.3.2 + image: greptime/greptimedb:v0.4.4 expose: - "4000" - "4001" diff --git a/.ci/docker-compose-file/docker-compose-kafka.yaml b/.ci/docker-compose-file/docker-compose-kafka.yaml index 352494592..d7ab6fe6f 100644 --- a/.ci/docker-compose-file/docker-compose-kafka.yaml +++ b/.ci/docker-compose-file/docker-compose-kafka.yaml @@ -18,7 +18,7 @@ services: - /tmp/emqx-ci/emqx-shared-secret:/var/lib/secret kdc: hostname: kdc.emqx.net - image: ghcr.io/emqx/emqx-builder/5.2-3:1.14.5-25.3.2-2-ubuntu22.04 + image: ghcr.io/emqx/emqx-builder/5.2-8:1.15.7-26.1.2-2-ubuntu22.04 container_name: kdc.emqx.net expose: - 88 # kdc diff --git a/.ci/docker-compose-file/docker-compose.yaml b/.ci/docker-compose-file/docker-compose.yaml index f3943b010..af2eced2c 100644 --- a/.ci/docker-compose-file/docker-compose.yaml +++ b/.ci/docker-compose-file/docker-compose.yaml @@ -3,7 +3,7 @@ version: '3.9' services: erlang: container_name: erlang - image: ${DOCKER_CT_RUNNER_IMAGE:-ghcr.io/emqx/emqx-builder/5.2-3:1.14.5-25.3.2-2-ubuntu22.04} + image: ${DOCKER_CT_RUNNER_IMAGE:-ghcr.io/emqx/emqx-builder/5.2-8:1.15.7-26.1.2-2-ubuntu22.04} env_file: - credentials.env - conf.env diff --git a/.github/actions/package-macos/action.yaml b/.github/actions/package-macos/action.yaml index 25edcb5f5..a2d89ac54 100644 --- a/.github/actions/package-macos/action.yaml +++ b/.github/actions/package-macos/action.yaml @@ -3,7 +3,7 @@ inputs: profile: # emqx, emqx-enterprise required: true type: string - otp: # 25.3.2-2 + otp: required: true type: string os: diff --git a/.github/workflows/_pr_entrypoint.yaml b/.github/workflows/_pr_entrypoint.yaml index 4a98f0808..6bfd66224 100644 --- a/.github/workflows/_pr_entrypoint.yaml +++ b/.github/workflows/_pr_entrypoint.yaml @@ -17,17 +17,17 @@ env: jobs: sanity-checks: runs-on: ubuntu-22.04 - container: "ghcr.io/emqx/emqx-builder/5.2-3:1.14.5-25.3.2-2-ubuntu22.04" + container: "ghcr.io/emqx/emqx-builder/5.2-8:1.15.7-26.1.2-2-ubuntu22.04" outputs: ct-matrix: ${{ steps.matrix.outputs.ct-matrix }} ct-host: ${{ steps.matrix.outputs.ct-host }} ct-docker: ${{ steps.matrix.outputs.ct-docker }} version-emqx: ${{ steps.matrix.outputs.version-emqx }} version-emqx-enterprise: ${{ steps.matrix.outputs.version-emqx-enterprise }} - builder: "ghcr.io/emqx/emqx-builder/5.2-3:1.14.5-25.3.2-2-ubuntu22.04" - builder_vsn: "5.2-3" - otp_vsn: "25.3.2-2" - elixir_vsn: "1.14.5" + builder: "ghcr.io/emqx/emqx-builder/5.2-8:1.15.7-26.1.2-2-ubuntu22.04" + builder_vsn: "5.2-8" + otp_vsn: "26.1.2-2" + elixir_vsn: "1.15.7" steps: - uses: actions/checkout@v3 @@ -92,14 +92,14 @@ jobs: MATRIX="$(echo "${APPS}" | jq -c ' [ (.[] | select(.profile == "emqx") | . + { - builder: "5.2-3", - otp: "25.3.2-2", - elixir: "1.14.5" + builder: "5.2-8", + otp: "26.1.2-2", + elixir: "1.15.7" }), (.[] | select(.profile == "emqx-enterprise") | . + { - builder: "5.2-3", - otp: ["25.3.2-2"][], - elixir: "1.14.5" + builder: "5.2-8", + otp: ["26.1.2-2"][], + elixir: "1.15.7" }) ] ')" diff --git a/.github/workflows/_push-entrypoint.yaml b/.github/workflows/_push-entrypoint.yaml index e2eff6dc7..92fe01847 100644 --- a/.github/workflows/_push-entrypoint.yaml +++ b/.github/workflows/_push-entrypoint.yaml @@ -20,7 +20,7 @@ env: jobs: prepare: runs-on: ubuntu-22.04 - container: 'ghcr.io/emqx/emqx-builder/5.2-3:1.14.5-25.3.2-2-ubuntu22.04' + container: 'ghcr.io/emqx/emqx-builder/5.2-8:1.15.7-26.1.2-2-ubuntu22.04' outputs: profile: ${{ steps.parse-git-ref.outputs.profile }} release: ${{ steps.parse-git-ref.outputs.release }} @@ -29,10 +29,10 @@ jobs: ct-matrix: ${{ steps.matrix.outputs.ct-matrix }} ct-host: ${{ steps.matrix.outputs.ct-host }} ct-docker: ${{ steps.matrix.outputs.ct-docker }} - builder: 'ghcr.io/emqx/emqx-builder/5.2-3:1.14.5-25.3.2-2-ubuntu22.04' - builder_vsn: '5.2-3' - otp_vsn: '25.3.2-2' - elixir_vsn: '1.14.5' + builder: 'ghcr.io/emqx/emqx-builder/5.2-8:1.15.7-26.1.2-2-ubuntu22.04' + builder_vsn: '5.2-8' + otp_vsn: '26.1.2-2' + elixir_vsn: '1.15.7' steps: - uses: actions/checkout@v3 @@ -62,14 +62,14 @@ jobs: MATRIX="$(echo "${APPS}" | jq -c ' [ (.[] | select(.profile == "emqx") | . + { - builder: "5.2-3", - otp: "25.3.2-2", - elixir: "1.14.5" + builder: "5.2-8", + otp: "26.1.2-2", + elixir: "1.15.7" }), (.[] | select(.profile == "emqx-enterprise") | . + { - builder: "5.2-3", - otp: ["25.3.2-2"][], - elixir: "1.14.5" + builder: "5.2-8", + otp: ["26.1.2-2"][], + elixir: "1.15.7" }) ] ')" diff --git a/.github/workflows/build_and_push_docker_images.yaml b/.github/workflows/build_and_push_docker_images.yaml index ba24be6c2..4d5357761 100644 --- a/.github/workflows/build_and_push_docker_images.yaml +++ b/.github/workflows/build_and_push_docker_images.yaml @@ -58,15 +58,15 @@ on: otp_vsn: required: false type: string - default: '25.3.2-2' + default: '26.1.2-2' elixir_vsn: required: false type: string - default: '1.14.5' + default: '1.15.7' builder_vsn: required: false type: string - default: '5.2-3' + default: '5.2-8' permissions: contents: read diff --git a/.github/workflows/build_packages.yaml b/.github/workflows/build_packages.yaml index 6d642ebef..4c1365f58 100644 --- a/.github/workflows/build_packages.yaml +++ b/.github/workflows/build_packages.yaml @@ -54,15 +54,15 @@ on: otp_vsn: required: false type: string - default: '25.3.2-2' + default: '26.1.2-2' elixir_vsn: required: false type: string - default: '1.14.5' + default: '1.15.7' builder_vsn: required: false type: string - default: '5.2-3' + default: '5.2-8' jobs: mac: diff --git a/.github/workflows/build_packages_cron.yaml b/.github/workflows/build_packages_cron.yaml index d29f2d64a..039e7392c 100644 --- a/.github/workflows/build_packages_cron.yaml +++ b/.github/workflows/build_packages_cron.yaml @@ -14,26 +14,18 @@ jobs: if: github.repository_owner == 'emqx' runs-on: ${{ endsWith(github.repository, '/emqx') && 'ubuntu-22.04' || fromJSON('["self-hosted","ephemeral","linux","x64"]') }} container: - image: "ghcr.io/emqx/emqx-builder/${{ matrix.builder }}:${{ matrix.elixir }}-${{ matrix.otp }}-${{ matrix.os }}" + image: "ghcr.io/emqx/emqx-builder/${{ matrix.profile[2] }}-${{ matrix.os }}" strategy: fail-fast: false matrix: profile: - - ['emqx', 'master'] - - ['emqx-enterprise', 'release-54'] - otp: - - 25.3.2-2 - arch: - - x64 + - ['emqx', 'master', '5.2-8:1.15.7-26.1.2-2'] + - ['emqx-enterprise', 'release-54', '5.2-3:1.14.5-25.3.2-2'] os: - debian10 - ubuntu22.04 - amzn2023 - builder: - - 5.2-3 - elixir: - - 1.14.5 defaults: run: @@ -98,7 +90,7 @@ jobs: branch: - master otp: - - 25.3.2-2 + - 26.1.2-2 os: - macos-12-arm64 diff --git a/.github/workflows/build_slim_packages.yaml b/.github/workflows/build_slim_packages.yaml index 2552655aa..a2b6131f4 100644 --- a/.github/workflows/build_slim_packages.yaml +++ b/.github/workflows/build_slim_packages.yaml @@ -27,19 +27,19 @@ on: builder: required: false type: string - default: 'ghcr.io/emqx/emqx-builder/5.2-3:1.14.5-25.3.2-2-ubuntu22.04' + default: 'ghcr.io/emqx/emqx-builder/5.2-8:1.15.7-26.1.2-2-ubuntu22.04' builder_vsn: required: false type: string - default: '5.2-3' + default: '5.2-8' otp_vsn: required: false type: string - default: '25.3.2-2' + default: '26.1.2-2' elixir_vsn: required: false type: string - default: '1.14.5' + default: '1.15.7' jobs: linux: @@ -51,8 +51,8 @@ jobs: fail-fast: false matrix: profile: - - ["emqx", "25.3.2-2", "ubuntu20.04", "elixir"] - - ["emqx-enterprise", "25.3.2-2", "ubuntu20.04", "erlang"] + - ["emqx", "26.1.2-2", "ubuntu20.04", "elixir"] + - ["emqx-enterprise", "26.1.2-2", "ubuntu20.04", "erlang"] container: "ghcr.io/emqx/emqx-builder/${{ inputs.builder_vsn }}:${{ inputs.elixir_vsn }}-${{ matrix.profile[1] }}-${{ matrix.profile[2] }}" diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index 3aad025db..5e0faa51d 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -20,7 +20,7 @@ jobs: actions: read security-events: write container: - image: ghcr.io/emqx/emqx-builder/5.2-3:1.14.5-25.3.2-2-ubuntu22.04 + image: ghcr.io/emqx/emqx-builder/5.2-8:1.15.7-26.1.2-2-ubuntu22.04 strategy: fail-fast: false diff --git a/.github/workflows/performance_test.yaml b/.github/workflows/performance_test.yaml index 1b6101f06..a8cfae5d8 100644 --- a/.github/workflows/performance_test.yaml +++ b/.github/workflows/performance_test.yaml @@ -26,7 +26,7 @@ jobs: prepare: runs-on: ubuntu-latest if: github.repository_owner == 'emqx' - container: ghcr.io/emqx/emqx-builder/5.2-3:1.14.5-25.3.2-2-ubuntu20.04 + container: ghcr.io/emqx/emqx-builder/5.2-8:1.15.7-26.1.2-2-ubuntu20.04 outputs: BENCH_ID: ${{ steps.prepare.outputs.BENCH_ID }} PACKAGE_FILE: ${{ steps.package_file.outputs.PACKAGE_FILE }} diff --git a/.github/workflows/run_relup_tests.yaml b/.github/workflows/run_relup_tests.yaml index 381e95753..d707a4f08 100644 --- a/.github/workflows/run_relup_tests.yaml +++ b/.github/workflows/run_relup_tests.yaml @@ -74,7 +74,7 @@ jobs: steps: - uses: erlef/setup-beam@v1.16.0 with: - otp-version: 25.3.2 + otp-version: 26.1.2 - uses: actions/checkout@v3 with: repository: hawk/lux diff --git a/.gitignore b/.gitignore index 6fd884057..0a76c3807 100644 --- a/.gitignore +++ b/.gitignore @@ -61,7 +61,7 @@ erlang_ls.config .envrc # elixir mix.lock -apps/emqx/test/emqx_static_checks_data/master.bpapi +apps/emqx/test/emqx_static_checks_data/master.bpapi2 # rendered configurations *.conf.rendered *.conf.rendered.* diff --git a/.tool-versions b/.tool-versions index 824207a4a..dec9fa563 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,2 +1,2 @@ -erlang 26.1.2-1 +erlang 26.1.2-2 elixir 1.15.7-otp-26 diff --git a/Makefile b/Makefile index 6897d7f5a..41ff1b024 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ REBAR = $(CURDIR)/rebar3 BUILD = $(CURDIR)/build SCRIPTS = $(CURDIR)/scripts export EMQX_RELUP ?= true -export EMQX_DEFAULT_BUILDER = ghcr.io/emqx/emqx-builder/5.1-4:1.14.5-25.3.2-2-debian11 +export EMQX_DEFAULT_BUILDER = ghcr.io/emqx/emqx-builder/5.2-8:1.15.7-26.1.2-2-debian11 export EMQX_DEFAULT_RUNNER = public.ecr.aws/debian/debian:11-slim export EMQX_REL_FORM ?= tgz export QUICER_DOWNLOAD_FROM_RELEASE = 1 @@ -102,7 +102,7 @@ endif # Allow user-set GROUPS environment variable ifneq ($(GROUPS),) -GROUPS_ARG := --groups $(GROUPS) +GROUPS_ARG := --group $(GROUPS) endif ifeq ($(ENABLE_COVER_COMPILE),1) diff --git a/README-RU.md b/README-RU.md index c22df7f3f..6cb7fda6a 100644 --- a/README-RU.md +++ b/README-RU.md @@ -83,7 +83,9 @@ docker run -d --name emqx -p 1883:1883 -p 8083:8083 -p 8883:8883 -p 8084:8084 -p Ветка `master` предназначена для последней версии 5, переключитесь на ветку `main-v4.4` для версии 4.4. -EMQX требует OTP 24 для версии 4.4. Версию 5.0 можно собирать с OTP 24 или 25. +EMQX требует OTP 24 для версии 4.4. +Версии 5.0 ~ 5.3 могут быть собраны с OTP 24 или 25. +Версия 5.4 и новее могут быть собраны с OTP 25 или 26. ```bash git clone https://github.com/emqx/emqx.git diff --git a/README.md b/README.md index 3624e90f8..3fda5999c 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,9 @@ For more organised improvement proposals, you can send pull requests to [EIP](ht The `master` branch tracks the latest version 5. For version 4.4 checkout the `main-v4.4` branch. -EMQX 4.4 requires OTP 24. EMQX 5.0 and 5.1 can be built with OTP 24 or 25. +EMQX 4.4 requires OTP 24. +EMQX 5.0 ~ 5.3 can be built with OTP 24 or 25. +EMQX 5.4 and newer can be built with OTP 24 or 25. ```bash git clone https://github.com/emqx/emqx.git diff --git a/apps/emqx/include/emqx_access_control.hrl b/apps/emqx/include/emqx_access_control.hrl index 65a159dd6..dee89f5a5 100644 --- a/apps/emqx/include/emqx_access_control.hrl +++ b/apps/emqx/include/emqx_access_control.hrl @@ -24,9 +24,13 @@ -define(DEFAULT_ACTION_QOS, 0). -define(DEFAULT_ACTION_RETAIN, false). +-define(AUTHZ_SUBSCRIBE_MATCH_MAP(QOS), #{action_type := subscribe, qos := QOS}). -define(AUTHZ_SUBSCRIBE(QOS), #{action_type => subscribe, qos => QOS}). -define(AUTHZ_SUBSCRIBE, ?AUTHZ_SUBSCRIBE(?DEFAULT_ACTION_QOS)). +-define(AUTHZ_PUBLISH_MATCH_MAP(QOS, RETAIN), #{ + action_type := publish, qos := QOS, retain := RETAIN +}). -define(AUTHZ_PUBLISH(QOS, RETAIN), #{action_type => publish, qos => QOS, retain => RETAIN}). -define(AUTHZ_PUBLISH(QOS), ?AUTHZ_PUBLISH(QOS, ?DEFAULT_ACTION_RETAIN)). -define(AUTHZ_PUBLISH, ?AUTHZ_PUBLISH(?DEFAULT_ACTION_QOS)). diff --git a/apps/emqx/priv/bpapi.versions b/apps/emqx/priv/bpapi.versions index e2c726fe5..208c34e30 100644 --- a/apps/emqx/priv/bpapi.versions +++ b/apps/emqx/priv/bpapi.versions @@ -19,6 +19,7 @@ {emqx_delayed,1}. {emqx_delayed,2}. {emqx_ds,1}. +{emqx_ds,2}. {emqx_eviction_agent,1}. {emqx_eviction_agent,2}. {emqx_exhook,1}. diff --git a/apps/emqx/rebar.config b/apps/emqx/rebar.config index 931e2bb8c..01b51ed88 100644 --- a/apps/emqx/rebar.config +++ b/apps/emqx/rebar.config @@ -66,7 +66,6 @@ {plt_location, "."}, {plt_prefix, "emqx_dialyzer"}, {plt_apps, all_apps}, - {plt_extra_apps, [hocon]}, {statistics, true} ]}. diff --git a/apps/emqx/rebar.config.script b/apps/emqx/rebar.config.script index 8f9de344c..66520b7f7 100644 --- a/apps/emqx/rebar.config.script +++ b/apps/emqx/rebar.config.script @@ -28,8 +28,7 @@ Quicer = {quicer, {git, "https://github.com/emqx/quic.git", {tag, "0.0.308"}}}. Dialyzer = fun(Config) -> {dialyzer, OldDialyzerConfig} = lists:keyfind(dialyzer, 1, Config), - {plt_extra_apps, OldExtra} = lists:keyfind(plt_extra_apps, 1, OldDialyzerConfig), - Extra = OldExtra ++ [quicer || IsQuicSupp()], + Extra = [quicer || IsQuicSupp()], NewDialyzerConfig = [{plt_extra_apps, Extra} | OldDialyzerConfig], lists:keystore( dialyzer, diff --git a/apps/emqx/src/bpapi/README.md b/apps/emqx/src/bpapi/README.md index f2177a88b..9c4bef959 100644 --- a/apps/emqx/src/bpapi/README.md +++ b/apps/emqx/src/bpapi/README.md @@ -145,12 +145,12 @@ free to cache it for the duration of the session. # New minor release -After releasing, let's say, 5.1.0, the following actions should be performed to prepare for the next release: +After releasing, let's say, 5.5.0, the following actions should be performed to prepare for the next release: -1. Checkout 5.1.0 tag +1. Checkout 5.5.0 tag 1. Build the code -1. Replace api version string `"master"` in `apps/emqx/test/emqx_static_checks_data/master.bpapi` with `"5.1"` -1. Rename `apps/emqx/test/emqx_static_checks_data/master.bpapi` to `apps/emqx/test/emqx_static_checks_data/5.1.bpapi` -1. Add `apps/emqx/test/emqx_static_checks_data/5.1.bpapi` to the repo -1. Delete the previous file (e.g. `5.0.bpapi`), unless there is plan to support rolling upgrade from 5.0 to 5.2 +1. Replace api version string `"master"` in `apps/emqx/test/emqx_static_checks_data/master.bpapi2` with `"5.5"` +1. Rename `apps/emqx/test/emqx_static_checks_data/master.bpapi` to `apps/emqx/test/emqx_static_checks_data/5.5.bpapi2` +1. Add `apps/emqx/test/emqx_static_checks_data/5.5.bpapi2` to the repo +1. Delete the previous file (e.g. `5.4.bpapi2`), unless there is plan to support rolling upgrade from 5.0. 1. Merge the commit to master branch diff --git a/apps/emqx/src/emqx.app.src b/apps/emqx/src/emqx.app.src index f837161be..43bcdc784 100644 --- a/apps/emqx/src/emqx.app.src +++ b/apps/emqx/src/emqx.app.src @@ -10,6 +10,7 @@ stdlib, gproc, gen_rpc, + mnesia, mria, ekka, esockd, @@ -17,7 +18,12 @@ sasl, lc, hocon, - emqx_durable_storage + emqx_durable_storage, + bcrypt, + pbkdf2, + emqx_http_lib, + recon, + os_mon ]}, {mod, {emqx_app, []}}, {env, []}, diff --git a/apps/emqx/src/emqx_access_control.erl b/apps/emqx/src/emqx_access_control.erl index 8aaa44eaa..ce594a15f 100644 --- a/apps/emqx/src/emqx_access_control.erl +++ b/apps/emqx/src/emqx_access_control.erl @@ -22,7 +22,8 @@ -export([ authenticate/1, - authorize/3 + authorize/3, + format_action/1 ]). -ifdef(TEST). @@ -152,6 +153,7 @@ do_authorize(ClientInfo, Action, Topic) -> case run_hooks('client.authorize', [ClientInfo, Action, Topic], Default) of AuthzResult = #{result := Result} when Result == allow; Result == deny -> From = maps:get(from, AuthzResult, unknown), + ok = log_result(ClientInfo, Topic, Action, From, NoMatch), emqx_hooks:run( 'client.check_authz_complete', [ClientInfo, Action, Topic, Result, From] @@ -170,6 +172,42 @@ do_authorize(ClientInfo, Action, Topic) -> deny end. +log_result(#{username := Username}, Topic, Action, From, Result) -> + LogMeta = fun() -> + #{ + username => Username, + topic => Topic, + action => format_action(Action), + source => format_from(From) + } + end, + case Result of + allow -> ?SLOG(info, (LogMeta())#{msg => "authorization_permission_allowed"}); + deny -> ?SLOG(warning, (LogMeta())#{msg => "authorization_permission_denied"}) + end. + +%% @private Format authorization rules source. +format_from(default) -> + "'authorization.no_match' config"; +format_from(unknown) -> + "'client.authorize' hook callback"; +format_from(Type) -> + Type. + +%% @doc Format enriched action info for logging. +format_action(?AUTHZ_SUBSCRIBE_MATCH_MAP(QoS)) -> + "SUBSCRIBE(" ++ format_qos(QoS) ++ ")"; +format_action(?AUTHZ_PUBLISH_MATCH_MAP(QoS, Retain)) -> + "PUBLISH(" ++ format_qos(QoS) ++ "," ++ format_retain_flag(Retain) ++ ")". + +format_qos(QoS) -> + "Q" ++ integer_to_list(QoS). + +format_retain_flag(true) -> + "R1"; +format_retain_flag(false) -> + "R0". + -compile({inline, [run_hooks/3]}). run_hooks(Name, Args, Acc) -> ok = emqx_metrics:inc(Name), diff --git a/apps/emqx/src/emqx_crl_cache.erl b/apps/emqx/src/emqx_crl_cache.erl index 45c76c7f4..4a0711523 100644 --- a/apps/emqx/src/emqx_crl_cache.erl +++ b/apps/emqx/src/emqx_crl_cache.erl @@ -24,7 +24,8 @@ register_der_crls/2, refresh/1, evict/1, - update_config/1 + update_config/1, + info/0 ]). %% gen_server callbacks @@ -104,6 +105,11 @@ update_config(Conf) -> register_der_crls(URL, CRLs) when is_list(CRLs) -> gen_server:cast(?MODULE, {register_der_crls, URL, CRLs}). +-spec info() -> #{atom() => _}. +info() -> + [state | State] = tuple_to_list(sys:get_state(?MODULE)), + maps:from_list(lists:zip(record_info(fields, state), State)). + %%-------------------------------------------------------------------- %% gen_server behaviour %%-------------------------------------------------------------------- diff --git a/apps/emqx/src/emqx_persistent_message_ds_replayer.erl b/apps/emqx/src/emqx_persistent_message_ds_replayer.erl index 723f02a01..1053978dc 100644 --- a/apps/emqx/src/emqx_persistent_message_ds_replayer.erl +++ b/apps/emqx/src/emqx_persistent_message_ds_replayer.erl @@ -113,8 +113,8 @@ n_inflight(#inflight{offset_ranges = Ranges}) -> fun (#ds_pubrange{type = ?T_CHECKPOINT}, N) -> N; - (#ds_pubrange{type = ?T_INFLIGHT, id = {_, First}, until = Until}, N) -> - N + range_size(First, Until) + (#ds_pubrange{type = ?T_INFLIGHT} = Range, N) -> + N + range_size(Range) end, 0, Ranges @@ -185,8 +185,12 @@ poll(PreprocFun, SessionId, Inflight0, WindowSize) when WindowSize > 0, WindowSi {[], Inflight0}; true -> %% TODO: Wrap this in `mria:async_dirty/2`? - Streams = shuffle(get_streams(SessionId)), - fetch(PreprocFun, SessionId, Inflight0, Streams, FreeSpace, []) + Checkpoints = find_checkpoints(Inflight0#inflight.offset_ranges), + StreamGroups = group_streams(get_streams(SessionId)), + {Publihes, Inflight} = + fetch(PreprocFun, SessionId, Inflight0, Checkpoints, StreamGroups, FreeSpace, []), + %% Discard now irrelevant QoS0-only ranges, if any. + {Publihes, discard_committed(SessionId, Inflight)} end. %% Which seqno this track is committed until. @@ -238,7 +242,7 @@ find_committed_until(Track, Ranges) -> Ranges ), case RangesUncommitted of - [#ds_pubrange{id = {_, CommittedUntil}} | _] -> + [#ds_pubrange{id = {_, CommittedUntil, _StreamRef}} | _] -> CommittedUntil; [] -> undefined @@ -249,28 +253,26 @@ get_ranges(SessionId) -> Pat = erlang:make_tuple( record_info(size, ds_pubrange), '_', - [{1, ds_pubrange}, {#ds_pubrange.id, {SessionId, '_'}}] + [{1, ds_pubrange}, {#ds_pubrange.id, {SessionId, '_', '_'}}] ), mnesia:match_object(?SESSION_PUBRANGE_TAB, Pat, read). -fetch(PreprocFun, SessionId, Inflight0, [DSStream | Streams], N, Acc) when N > 0 -> +fetch(PreprocFun, SessionId, Inflight0, CPs, Groups, N, Acc) when N > 0, Groups =/= [] -> #inflight{next_seqno = FirstSeqno, offset_ranges = Ranges} = Inflight0, - ItBegin = get_last_iterator(DSStream, Ranges), - {ok, ItEnd, Messages} = emqx_ds:next(?PERSISTENT_MESSAGE_DB, ItBegin, N), - case Messages of + {Stream, Groups2} = get_the_first_stream(Groups), + case get_next_n_messages_from_stream(Stream, CPs, N) of [] -> - fetch(PreprocFun, SessionId, Inflight0, Streams, N, Acc); - _ -> + fetch(PreprocFun, SessionId, Inflight0, CPs, Groups2, N, Acc); + {ItBegin, ItEnd, Messages} -> %% We need to preserve the iterator pointing to the beginning of the %% range, so that we can replay it if needed. {Publishes, UntilSeqno} = publish_fetch(PreprocFun, FirstSeqno, Messages), Size = range_size(FirstSeqno, UntilSeqno), Range0 = #ds_pubrange{ - id = {SessionId, FirstSeqno}, + id = {SessionId, FirstSeqno, Stream#ds_stream.ref}, type = ?T_INFLIGHT, tracks = compute_pub_tracks(Publishes), until = UntilSeqno, - stream = DSStream#ds_stream.ref, iterator = ItBegin }, ok = preserve_range(Range0), @@ -282,9 +284,9 @@ fetch(PreprocFun, SessionId, Inflight0, [DSStream | Streams], N, Acc) when N > 0 next_seqno = UntilSeqno, offset_ranges = Ranges ++ [Range] }, - fetch(PreprocFun, SessionId, Inflight, Streams, N - Size, [Publishes | Acc]) + fetch(PreprocFun, SessionId, Inflight, CPs, Groups2, N - Size, [Publishes | Acc]) end; -fetch(_ReplyFun, _SessionId, Inflight, _Streams, _N, Acc) -> +fetch(_ReplyFun, _SessionId, Inflight, _CPs, _Groups, _N, Acc) -> Publishes = lists:append(lists:reverse(Acc)), {Publishes, Inflight}. @@ -300,9 +302,9 @@ discard_committed( find_checkpoints(Ranges) -> lists:foldl( - fun(#ds_pubrange{stream = StreamRef, until = Until}, Acc) -> + fun(#ds_pubrange{id = {_SessionId, _, StreamRef}} = Range, Acc) -> %% For each stream, remember the last range over this stream. - Acc#{StreamRef => Until} + Acc#{StreamRef => Range} end, #{}, Ranges @@ -312,7 +314,7 @@ discard_committed_ranges( SessionId, Commits, Checkpoints, - Ranges = [Range = #ds_pubrange{until = Until, stream = StreamRef} | Rest] + Ranges = [Range = #ds_pubrange{id = {_SessionId, _, StreamRef}} | Rest] ) -> case discard_committed_range(Commits, Range) of discard -> @@ -321,11 +323,11 @@ discard_committed_ranges( %% over this stream (i.e. a checkpoint). RangeKept = case maps:get(StreamRef, Checkpoints) of - CP when CP > Until -> + Range -> + [checkpoint_range(Range)]; + _Previous -> discard_range(Range), - []; - Until -> - [checkpoint_range(Range)] + [] end, %% Since we're (intentionally) not using transactions here, it's important to %% issue database writes in the same order in which ranges are stored: from @@ -381,7 +383,9 @@ discard_tracks(#{ack := AckedUntil, comp := CompUntil}, Until, Tracks) -> replay_range( PreprocFun, Commits, - Range0 = #ds_pubrange{type = ?T_INFLIGHT, id = {_, First}, until = Until, iterator = It}, + Range0 = #ds_pubrange{ + type = ?T_INFLIGHT, id = {_, First, _StreamRef}, until = Until, iterator = It + }, Acc ) -> Size = range_size(First, Until), @@ -427,7 +431,7 @@ get_commit_next(comp, #inflight{commits = Commits}) -> publish_fetch(PreprocFun, FirstSeqno, Messages) -> flatmapfoldl( - fun(MessageIn, Acc) -> + fun({_DSKey, MessageIn}, Acc) -> Message = PreprocFun(MessageIn), publish_fetch(Message, Acc) end, @@ -446,7 +450,7 @@ publish_fetch(Messages, Seqno) -> publish_replay(PreprocFun, Commits, FirstSeqno, Messages) -> #{ack := AckedUntil, comp := CompUntil, rec := RecUntil} = Commits, flatmapfoldl( - fun(MessageIn, Acc) -> + fun({_DSKey, MessageIn}, Acc) -> Message = PreprocFun(MessageIn), publish_replay(Message, AckedUntil, CompUntil, RecUntil, Acc) end, @@ -545,10 +549,10 @@ checkpoint_range(Range = #ds_pubrange{type = ?T_CHECKPOINT}) -> %% This range should have been checkpointed already. Range. -get_last_iterator(DSStream = #ds_stream{ref = StreamRef}, Ranges) -> - case lists:keyfind(StreamRef, #ds_pubrange.stream, lists:reverse(Ranges)) of - false -> - DSStream#ds_stream.beginning; +get_last_iterator(Stream = #ds_stream{ref = StreamRef}, Checkpoints) -> + case maps:get(StreamRef, Checkpoints, none) of + none -> + Stream#ds_stream.beginning; #ds_pubrange{iterator = ItNext} -> ItNext end. @@ -593,16 +597,32 @@ packet_id_to_seqno_(NextSeqno, PacketId) -> N - ?EPOCH_SIZE end. +range_size(#ds_pubrange{id = {_, First, _StreamRef}, until = Until}) -> + range_size(First, Until). + range_size(FirstSeqno, UntilSeqno) -> %% This function assumes that gaps in the sequence ID occur _only_ when the %% packet ID wraps. Size = UntilSeqno - FirstSeqno, Size + (FirstSeqno bsr 16) - (UntilSeqno bsr 16). +%%================================================================================ +%% stream scheduler + +%% group streams by the first position in the rank +-spec group_streams(list(ds_stream())) -> list(list(ds_stream())). +group_streams(Streams) -> + Groups = maps:groups_from_list( + fun(#ds_stream{rank = {RankX, _}}) -> RankX end, + Streams + ), + shuffle(maps:values(Groups)). + -spec shuffle([A]) -> [A]. shuffle(L0) -> L1 = lists:map( fun(A) -> + %% maybe topic/stream prioritization could be introduced here? {rand:uniform(), A} end, L0 @@ -611,6 +631,47 @@ shuffle(L0) -> {_, L} = lists:unzip(L2), L. +get_the_first_stream([Group | Groups]) -> + case get_next_stream_from_group(Group) of + {Stream, {sorted, []}} -> + {Stream, Groups}; + {Stream, Group2} -> + {Stream, [Group2 | Groups]}; + undefined -> + get_the_first_stream(Groups) + end; +get_the_first_stream([]) -> + %% how this possible ? + throw(#{reason => no_valid_stream}). + +%% the scheduler is simple, try to get messages from the same shard, but it's okay to take turns +get_next_stream_from_group({sorted, [H | T]}) -> + {H, {sorted, T}}; +get_next_stream_from_group({sorted, []}) -> + undefined; +get_next_stream_from_group(Streams) -> + [Stream | T] = lists:sort( + fun(#ds_stream{rank = {_, RankA}}, #ds_stream{rank = {_, RankB}}) -> + RankA < RankB + end, + Streams + ), + {Stream, {sorted, T}}. + +get_next_n_messages_from_stream(Stream, CPs, N) -> + ItBegin = get_last_iterator(Stream, CPs), + case emqx_ds:next(?PERSISTENT_MESSAGE_DB, ItBegin, N) of + {ok, _ItEnd, []} -> + []; + {ok, ItEnd, Messages} -> + {ItBegin, ItEnd, Messages}; + {ok, end_of_stream} -> + %% TODO: how to skip this closed stream or it should be taken over by lower level layer + [] + end. + +%%================================================================================ + -spec flatmapfoldl(fun((X, Acc) -> {Y | [Y], Acc}), Acc, [X]) -> {[Y], Acc}. flatmapfoldl(_Fun, Acc, []) -> {[], Acc}; @@ -697,23 +758,23 @@ compute_inflight_range_test_() -> ?_assertEqual( {#{ack => 12, comp => 13}, 42}, compute_inflight_range([ - #ds_pubrange{id = {<<>>, 1}, until = 2, type = ?T_CHECKPOINT}, - #ds_pubrange{id = {<<>>, 4}, until = 8, type = ?T_CHECKPOINT}, - #ds_pubrange{id = {<<>>, 11}, until = 12, type = ?T_CHECKPOINT}, + #ds_pubrange{id = {<<>>, 1, 0}, until = 2, type = ?T_CHECKPOINT}, + #ds_pubrange{id = {<<>>, 4, 0}, until = 8, type = ?T_CHECKPOINT}, + #ds_pubrange{id = {<<>>, 11, 0}, until = 12, type = ?T_CHECKPOINT}, #ds_pubrange{ - id = {<<>>, 12}, + id = {<<>>, 12, 0}, until = 13, type = ?T_INFLIGHT, tracks = ?TRACK_FLAG(?ACK) }, #ds_pubrange{ - id = {<<>>, 13}, + id = {<<>>, 13, 0}, until = 20, type = ?T_INFLIGHT, tracks = ?TRACK_FLAG(?COMP) }, #ds_pubrange{ - id = {<<>>, 20}, + id = {<<>>, 20, 0}, until = 42, type = ?T_INFLIGHT, tracks = ?TRACK_FLAG(?ACK) bor ?TRACK_FLAG(?COMP) @@ -723,10 +784,10 @@ compute_inflight_range_test_() -> ?_assertEqual( {#{ack => 13, comp => 13}, 13}, compute_inflight_range([ - #ds_pubrange{id = {<<>>, 1}, until = 2, type = ?T_CHECKPOINT}, - #ds_pubrange{id = {<<>>, 4}, until = 8, type = ?T_CHECKPOINT}, - #ds_pubrange{id = {<<>>, 11}, until = 12, type = ?T_CHECKPOINT}, - #ds_pubrange{id = {<<>>, 12}, until = 13, type = ?T_CHECKPOINT} + #ds_pubrange{id = {<<>>, 1, 0}, until = 2, type = ?T_CHECKPOINT}, + #ds_pubrange{id = {<<>>, 4, 0}, until = 8, type = ?T_CHECKPOINT}, + #ds_pubrange{id = {<<>>, 11, 0}, until = 12, type = ?T_CHECKPOINT}, + #ds_pubrange{id = {<<>>, 12, 0}, until = 13, type = ?T_CHECKPOINT} ]) ) ]. diff --git a/apps/emqx/src/emqx_persistent_session_ds.erl b/apps/emqx/src/emqx_persistent_session_ds.erl index a1db2e933..a8c62fe7a 100644 --- a/apps/emqx/src/emqx_persistent_session_ds.erl +++ b/apps/emqx/src/emqx_persistent_session_ds.erl @@ -214,8 +214,8 @@ info(subscriptions_max, #{props := Conf}) -> maps:get(max_subscriptions, Conf); info(upgrade_qos, #{props := Conf}) -> maps:get(upgrade_qos, Conf); -% info(inflight, #sessmem{inflight = Inflight}) -> -% Inflight; +info(inflight, #{inflight := Inflight}) -> + Inflight; info(inflight_cnt, #{inflight := Inflight}) -> emqx_persistent_message_ds_replayer:n_inflight(Inflight); info(inflight_max, #{receive_maximum := ReceiveMaximum}) -> @@ -433,7 +433,8 @@ handle_timeout( {ok, Publishes, Session}; handle_timeout(_ClientInfo, ?TIMER_GET_STREAMS, Session) -> renew_streams(Session), - {ok, [], emqx_session:ensure_timer(?TIMER_GET_STREAMS, 100, Session)}; + Interval = emqx_config:get([session_persistence, renew_streams_interval]), + {ok, [], emqx_session:ensure_timer(?TIMER_GET_STREAMS, Interval, Session)}; handle_timeout(_ClientInfo, ?TIMER_BUMP_LAST_ALIVE_AT, Session0) -> %% Note: we take a pessimistic approach here and assume that the client will be alive %% until the next bump timeout. With this, we avoid garbage collecting this session @@ -791,8 +792,8 @@ session_read_pubranges(DSSessionID) -> session_read_pubranges(DSSessionId, LockKind) -> MS = ets:fun2ms( - fun(#ds_pubrange{id = {Sess, First}}) when Sess =:= DSSessionId -> - {DSSessionId, First} + fun(#ds_pubrange{id = ID}) when element(1, ID) =:= DSSessionId -> + ID end ), mnesia:select(?SESSION_PUBRANGE_TAB, MS, LockKind). @@ -1083,10 +1084,15 @@ list_all_streams() -> list_all_pubranges() -> DSPubranges = mnesia:dirty_match_object(?SESSION_PUBRANGE_TAB, #ds_pubrange{_ = '_'}), lists:foldl( - fun(Record = #ds_pubrange{id = {SessionId, First}}, Acc) -> - Range = export_record( - Record, #ds_pubrange.until, [until, stream, type, iterator], #{first => First} - ), + fun(Record = #ds_pubrange{id = {SessionId, First, StreamRef}}, Acc) -> + Range = #{ + session => SessionId, + stream => StreamRef, + first => First, + until => Record#ds_pubrange.until, + type => Record#ds_pubrange.type, + iterator => Record#ds_pubrange.iterator + }, maps:put(SessionId, maps:get(SessionId, Acc, []) ++ [Range], Acc) end, #{}, diff --git a/apps/emqx/src/emqx_persistent_session_ds.hrl b/apps/emqx/src/emqx_persistent_session_ds.hrl index 306e63b2e..31c9b2faf 100644 --- a/apps/emqx/src/emqx_persistent_session_ds.hrl +++ b/apps/emqx/src/emqx_persistent_session_ds.hrl @@ -50,20 +50,18 @@ %% What session this range belongs to. _Session :: emqx_persistent_session_ds:id(), %% Where this range starts. - _First :: emqx_persistent_message_ds_replayer:seqno() + _First :: emqx_persistent_message_ds_replayer:seqno(), + %% Which stream this range is over. + _StreamRef }, %% Where this range ends: the first seqno that is not included in the range. until :: emqx_persistent_message_ds_replayer:seqno(), - %% Which stream this range is over. - stream :: _StreamRef, %% Type of a range: %% * Inflight range is a range of yet unacked messages from this stream. %% * Checkpoint range was already acked, its purpose is to keep track of the %% very last iterator for this stream. type :: ?T_INFLIGHT | ?T_CHECKPOINT, %% What commit tracks this range is part of. - %% This is rarely stored: we only need to persist it when the range contains - %% QoS 2 messages. tracks = 0 :: non_neg_integer(), %% Meaning of this depends on the type of the range: %% * For inflight range, this is the iterator pointing to the first message in diff --git a/apps/emqx/src/emqx_persistent_session_ds_gc_worker.erl b/apps/emqx/src/emqx_persistent_session_ds_gc_worker.erl index bf607804f..af387d2ca 100644 --- a/apps/emqx/src/emqx_persistent_session_ds_gc_worker.erl +++ b/apps/emqx/src/emqx_persistent_session_ds_gc_worker.erl @@ -82,7 +82,7 @@ try_gc() -> CoreNodes = mria_membership:running_core_nodelist(), Res = global:trans( {?MODULE, self()}, - fun() -> ?tp_span(ds_session_gc, #{}, start_gc()) end, + fun() -> ?tp_span(debug, ds_session_gc, #{}, start_gc()) end, CoreNodes, %% Note: we set retries to 1 here because, in rare occasions, GC might start at the %% same time in more than one node, and each one will abort the other. By allowing diff --git a/apps/emqx/src/emqx_router_utils.erl b/apps/emqx/src/emqx_router_utils.erl index 9fab86d37..146d9db52 100644 --- a/apps/emqx/src/emqx_router_utils.erl +++ b/apps/emqx/src/emqx_router_utils.erl @@ -19,18 +19,11 @@ -include("emqx.hrl"). -export([ - delete_direct_route/2, delete_trie_route/2, - delete_session_trie_route/2, - insert_direct_route/2, insert_trie_route/2, - insert_session_trie_route/2, maybe_trans/3 ]). -insert_direct_route(Tab, Route) -> - mria:dirty_write(Tab, Route). - insert_trie_route(RouteTab, Route = #route{topic = Topic}) -> case mnesia:wread({RouteTab, Topic}) of [] -> emqx_trie:insert(Topic); @@ -38,31 +31,12 @@ insert_trie_route(RouteTab, Route = #route{topic = Topic}) -> end, mnesia:write(RouteTab, Route, sticky_write). -insert_session_trie_route(RouteTab, Route = #route{topic = Topic}) -> - case mnesia:wread({RouteTab, Topic}) of - [] -> emqx_trie:insert_session(Topic); - _ -> ok - end, - mnesia:write(RouteTab, Route, sticky_write). - -delete_direct_route(RouteTab, Route) -> - mria:dirty_delete_object(RouteTab, Route). - -delete_trie_route(RouteTab, Route) -> - delete_trie_route(RouteTab, Route, normal). - -delete_session_trie_route(RouteTab, Route) -> - delete_trie_route(RouteTab, Route, session). - -delete_trie_route(RouteTab, Route = #route{topic = Topic}, Type) -> +delete_trie_route(RouteTab, Route = #route{topic = Topic}) -> case mnesia:wread({RouteTab, Topic}) of [R] when R =:= Route -> %% Remove route and trie ok = mnesia:delete_object(RouteTab, Route, sticky_write), - case Type of - normal -> emqx_trie:delete(Topic); - session -> emqx_trie:delete_session(Topic) - end; + emqx_trie:delete(Topic); [_ | _] -> %% Remove route only mnesia:delete_object(RouteTab, Route, sticky_write); diff --git a/apps/emqx/src/emqx_schema.erl b/apps/emqx/src/emqx_schema.erl index c6efe6e46..2b795d85d 100644 --- a/apps/emqx/src/emqx_schema.erl +++ b/apps/emqx/src/emqx_schema.erl @@ -1805,6 +1805,14 @@ fields("session_persistence") -> desc => ?DESC(session_ds_last_alive_update_interval) } )}, + {"renew_streams_interval", + sc( + timeout_duration(), + #{ + default => <<"5000ms">>, + importance => ?IMPORTANCE_HIDDEN + } + )}, {"session_gc_interval", sc( timeout_duration(), diff --git a/apps/emqx/src/emqx_session.erl b/apps/emqx/src/emqx_session.erl index 7604c2ba5..c08109fe8 100644 --- a/apps/emqx/src/emqx_session.erl +++ b/apps/emqx/src/emqx_session.erl @@ -175,19 +175,11 @@ %% Behaviour %% ------------------------------------------------------------------- --if(?OTP_RELEASE < 26). --callback create(clientinfo(), conninfo(), conf()) -> - term(). --callback open(clientinfo(), conninfo(), conf()) -> - term(). --callback destroy(t() | clientinfo()) -> ok. --else. -callback create(clientinfo(), conninfo(), conf()) -> t(). -callback open(clientinfo(), conninfo(), conf()) -> {_IsPresent :: true, t(), _ReplayContext} | false. -callback destroy(t() | clientinfo()) -> ok. --endif. %%-------------------------------------------------------------------- %% Create a Session diff --git a/apps/emqx/src/emqx_session_router_worker.erl b/apps/emqx/src/emqx_session_router_worker.erl deleted file mode 100644 index b55305d3e..000000000 --- a/apps/emqx/src/emqx_session_router_worker.erl +++ /dev/null @@ -1,163 +0,0 @@ -%%-------------------------------------------------------------------- -%% Copyright (c) 2021-2023 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. -%%-------------------------------------------------------------------- - -%% @doc The session router worker is responsible for buffering -%% messages for a persistent session while it is initializing. If a -%% connection process exists for a persistent session, this process is -%% used for bridging the gap while the new connection process takes -%% over the persistent session, but if there is no such process this -%% worker takes it place. -%% -%% The workers are started on all nodes, and buffers all messages that -%% are persisted to the session message table. In the final stage of -%% the initialization, the messages are delivered and the worker is -%% terminated. - --module(emqx_session_router_worker). - --behaviour(gen_server). - -%% API --export([ - buffer/3, - pendings/1, - resume_end/3, - start_link/2 -]). - -%% gen_server callbacks --export([ - init/1, - handle_call/3, - handle_cast/2, - handle_info/2, - terminate/2 -]). - --include_lib("snabbkaffe/include/snabbkaffe.hrl"). - --record(state, { - remote_pid :: pid(), - session_id :: binary(), - session_tab :: ets:table(), - messages :: ets:table(), - buffering :: boolean() -}). - -%%%=================================================================== -%%% API -%%%=================================================================== - -start_link(SessionTab, #{} = Opts) -> - gen_server:start_link(?MODULE, Opts#{session_tab => SessionTab}, []). - -pendings(Pid) -> - gen_server:call(Pid, pendings). - -resume_end(RemotePid, Pid, _SessionID) -> - case gen_server:call(Pid, {resume_end, RemotePid}) of - {ok, EtsHandle} -> - ?tp(ps_worker_call_ok, #{ - pid => Pid, - remote_pid => RemotePid, - sid => _SessionID - }), - {ok, ets:tab2list(EtsHandle)}; - {error, _} = Err -> - ?tp(ps_worker_call_failed, #{ - pid => Pid, - remote_pid => RemotePid, - sid => _SessionID, - reason => Err - }), - Err - end. - -buffer(Worker, STopic, Msg) -> - Worker ! {buffer, STopic, Msg}, - ok. - -%%%=================================================================== -%%% gen_server callbacks -%%%=================================================================== - -init(#{ - remote_pid := RemotePid, - session_id := SessionID, - session_tab := SessionTab -}) -> - process_flag(trap_exit, true), - erlang:monitor(process, RemotePid), - ?tp(ps_worker_started, #{ - remote_pid => RemotePid, - sid => SessionID - }), - {ok, #state{ - remote_pid = RemotePid, - session_id = SessionID, - session_tab = SessionTab, - messages = ets:new(?MODULE, [protected, ordered_set]), - buffering = true - }}. - -handle_call(pendings, _From, State) -> - %% Debug API - {reply, {State#state.messages, State#state.remote_pid}, State}; -handle_call({resume_end, RemotePid}, _From, #state{remote_pid = RemotePid} = State) -> - ?tp(ps_worker_resume_end, #{sid => State#state.session_id}), - {reply, {ok, State#state.messages}, State#state{buffering = false}}; -handle_call({resume_end, _RemotePid}, _From, State) -> - ?tp(ps_worker_resume_end_error, #{sid => State#state.session_id}), - {reply, {error, wrong_remote_pid}, State}; -handle_call(_Request, _From, State) -> - Reply = ok, - {reply, Reply, State}. - -handle_cast(_Request, State) -> - {noreply, State}. - -handle_info({buffer, _STopic, _Msg}, State) when not State#state.buffering -> - ?tp(ps_worker_drop_deliver, #{ - sid => State#state.session_id, - msg_id => emqx_message:id(_Msg) - }), - {noreply, State}; -handle_info({buffer, STopic, Msg}, State) when State#state.buffering -> - ?tp(ps_worker_deliver, #{ - sid => State#state.session_id, - msg_id => emqx_message:id(Msg) - }), - ets:insert(State#state.messages, {{Msg, STopic}}), - {noreply, State}; -handle_info({'DOWN', _, process, RemotePid, _Reason}, #state{remote_pid = RemotePid} = State) -> - ?tp(warning, ps_worker, #{ - event => worker_remote_died, - sid => State#state.session_id, - msg => "Remote pid died. Exiting." - }), - {stop, normal, State}; -handle_info(_Info, State) -> - {noreply, State}. - -terminate(shutdown, _State) -> - ?tp(ps_worker_shutdown, #{sid => _State#state.session_id}), - ok; -terminate(_, _State) -> - ok. - -%%%=================================================================== -%%% Internal functions -%%%=================================================================== diff --git a/apps/emqx/src/emqx_session_router_worker_sup.erl b/apps/emqx/src/emqx_session_router_worker_sup.erl deleted file mode 100644 index 473f9ccd2..000000000 --- a/apps/emqx/src/emqx_session_router_worker_sup.erl +++ /dev/null @@ -1,64 +0,0 @@ -%%-------------------------------------------------------------------- -%% Copyright (c) 2021-2023 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. -%%-------------------------------------------------------------------- - --module(emqx_session_router_worker_sup). - --behaviour(supervisor). - --export([start_link/1]). - --export([ - abort_worker/1, - start_worker/2 -]). - --export([init/1]). - -start_link(SessionTab) -> - supervisor:start_link({local, ?MODULE}, ?MODULE, SessionTab). - -start_worker(SessionID, RemotePid) -> - supervisor:start_child(?MODULE, [ - #{ - session_id => SessionID, - remote_pid => RemotePid - } - ]). - -abort_worker(Pid) -> - supervisor:terminate_child(?MODULE, Pid). - -%%-------------------------------------------------------------------- -%% Supervisor callbacks -%%-------------------------------------------------------------------- - -init(SessionTab) -> - %% Resume worker - Worker = #{ - id => session_router_worker, - start => {emqx_session_router_worker, start_link, [SessionTab]}, - restart => transient, - shutdown => 2000, - type => worker, - modules => [emqx_session_router_worker] - }, - Spec = #{ - strategy => simple_one_for_one, - intensity => 1, - period => 5 - }, - - {ok, {Spec, [Worker]}}. diff --git a/apps/emqx/test/emqx_SUITE.erl b/apps/emqx/test/emqx_SUITE.erl index d2e26232f..779038045 100644 --- a/apps/emqx/test/emqx_SUITE.erl +++ b/apps/emqx/test/emqx_SUITE.erl @@ -26,12 +26,11 @@ all() -> emqx_common_test_helpers:all(?MODULE). init_per_suite(Config) -> - emqx_common_test_helpers:boot_modules(all), - emqx_common_test_helpers:start_apps([]), - Config. + Apps = emqx_cth_suite:start([emqx], #{work_dir => emqx_cth_suite:work_dir(Config)}), + [{apps, Apps} | Config]. -end_per_suite(_Config) -> - emqx_common_test_helpers:stop_apps([]). +end_per_suite(Config) -> + emqx_cth_suite:stop(?config(apps, Config)). t_emqx_pubsub_api(_) -> true = emqx:is_running(node()), diff --git a/apps/emqx/test/emqx_access_control_SUITE.erl b/apps/emqx/test/emqx_access_control_SUITE.erl index 8f7a1fa6c..188a46e5d 100644 --- a/apps/emqx/test/emqx_access_control_SUITE.erl +++ b/apps/emqx/test/emqx_access_control_SUITE.erl @@ -26,12 +26,14 @@ all() -> emqx_common_test_helpers:all(?MODULE). init_per_suite(Config) -> - emqx_common_test_helpers:boot_modules([broker]), - emqx_common_test_helpers:start_apps([]), - Config. + Apps = emqx_cth_suite:start( + [{emqx, #{override_env => [{boot_modules, [broker]}]}}], + #{work_dir => emqx_cth_suite:work_dir(Config)} + ), + [{apps, Apps} | Config]. -end_per_suite(_Config) -> - emqx_common_test_helpers:stop_apps([]). +end_per_suite(Config) -> + emqx_cth_suite:stop(proplists:get_value(apps, Config)). init_per_testcase(_, Config) -> Config. diff --git a/apps/emqx/test/emqx_alarm_SUITE.erl b/apps/emqx/test/emqx_alarm_SUITE.erl index 49dd4c240..385e7ca51 100644 --- a/apps/emqx/test/emqx_alarm_SUITE.erl +++ b/apps/emqx/test/emqx_alarm_SUITE.erl @@ -19,29 +19,25 @@ -compile(export_all). -compile(nowarn_export_all). --include_lib("emqx/include/emqx.hrl"). --include_lib("emqx/include/emqx_mqtt.hrl"). -include_lib("eunit/include/eunit.hrl"). all() -> emqx_common_test_helpers:all(?MODULE). -init_per_testcase(t_size_limit, Config) -> - emqx_common_test_helpers:boot_modules(all), - emqx_common_test_helpers:start_apps([]), - {ok, _} = emqx:update_config([alarm], #{ - <<"size_limit">> => 2 - }), - Config; -init_per_testcase(_, Config) -> - emqx_common_test_helpers:boot_modules(all), - emqx_common_test_helpers:start_apps([]), - {ok, _} = emqx:update_config([alarm], #{ - <<"validity_period">> => <<"1s">> - }), - Config. +init_per_testcase(t_size_limit = TC, Config) -> + Apps = emqx_cth_suite:start( + [{emqx, "alarm.size_limit = 2"}], + #{work_dir => emqx_cth_suite:work_dir(TC, Config)} + ), + [{apps, Apps} | Config]; +init_per_testcase(TC, Config) -> + Apps = emqx_cth_suite:start( + [{emqx, "alarm.validity_period = \"1s\""}], + #{work_dir => emqx_cth_suite:work_dir(TC, Config)} + ), + [{apps, Apps} | Config]. -end_per_testcase(_, _Config) -> - emqx_common_test_helpers:stop_apps([]). +end_per_testcase(_, Config) -> + emqx_cth_suite:stop(proplists:get_value(apps, Config)). t_alarm(_) -> ok = emqx_alarm:activate(unknown_alarm), diff --git a/apps/emqx/test/emqx_authz_cache_SUITE.erl b/apps/emqx/test/emqx_authz_cache_SUITE.erl index 09d1e1522..53e38c8f1 100644 --- a/apps/emqx/test/emqx_authz_cache_SUITE.erl +++ b/apps/emqx/test/emqx_authz_cache_SUITE.erl @@ -24,12 +24,11 @@ all() -> emqx_common_test_helpers:all(?MODULE). init_per_suite(Config) -> - emqx_common_test_helpers:boot_modules(all), - emqx_common_test_helpers:start_apps([]), - Config. + Apps = emqx_cth_suite:start([emqx], #{work_dir => emqx_cth_suite:work_dir(Config)}), + [{apps, Apps} | Config]. -end_per_suite(_Config) -> - emqx_common_test_helpers:stop_apps([]). +end_per_suite(Config) -> + emqx_cth_suite:stop(proplists:get_value(apps, Config)). %%-------------------------------------------------------------------- %% Test cases diff --git a/apps/emqx/test/emqx_banned_SUITE.erl b/apps/emqx/test/emqx_banned_SUITE.erl index 47134c666..8c86e17f6 100644 --- a/apps/emqx/test/emqx_banned_SUITE.erl +++ b/apps/emqx/test/emqx_banned_SUITE.erl @@ -26,15 +26,11 @@ all() -> emqx_common_test_helpers:all(?MODULE). init_per_suite(Config) -> - emqx_common_test_helpers:start_apps([]), - ok = ekka:start(), - Config. + Apps = emqx_cth_suite:start([emqx], #{work_dir => emqx_cth_suite:work_dir(Config)}), + [{apps, Apps} | Config]. -end_per_suite(_Config) -> - ekka:stop(), - mria:stop(), - mria_mnesia:delete_schema(), - emqx_common_test_helpers:stop_apps([]). +end_per_suite(Config) -> + emqx_cth_suite:stop(proplists:get_value(apps, Config)). t_add_delete(_) -> Banned = #banned{ diff --git a/apps/emqx/test/emqx_boot_SUITE.erl b/apps/emqx/test/emqx_boot_SUITE.erl index 006888d9c..323bc7591 100644 --- a/apps/emqx/test/emqx_boot_SUITE.erl +++ b/apps/emqx/test/emqx_boot_SUITE.erl @@ -23,6 +23,13 @@ all() -> emqx_common_test_helpers:all(?MODULE). +init_per_suite(Config) -> + ok = application:load(emqx), + Config. + +end_per_suite(_) -> + ok = application:unload(emqx). + t_is_enabled(_) -> try ok = application:set_env(emqx, boot_modules, all), diff --git a/apps/emqx/test/emqx_bpapi_SUITE.erl b/apps/emqx/test/emqx_bpapi_SUITE.erl index 5e29071a2..d9a0a1b20 100644 --- a/apps/emqx/test/emqx_bpapi_SUITE.erl +++ b/apps/emqx/test/emqx_bpapi_SUITE.erl @@ -26,16 +26,13 @@ all() -> emqx_common_test_helpers:all(?MODULE). init_per_suite(Config) -> - emqx_common_test_helpers:start_apps([emqx]), + Apps = emqx_cth_suite:start([emqx], #{work_dir => emqx_cth_suite:work_dir(Config)}), [mnesia:dirty_write(Rec) || Rec <- fake_records()], - Config. + [{apps, Apps} | Config]. -end_per_suite(_Config) -> +end_per_suite(Config) -> meck:unload(), - [mnesia:dirty_delete({?TAB, Key}) || #?TAB{key = Key} <- fake_records()], - emqx_bpapi:announce(emqx), - emqx_common_test_helpers:stop_apps([emqx]), - ok. + emqx_cth_suite:stop(?config(apps, Config)). t_max_supported_version(_Config) -> ?assertMatch(3, emqx_bpapi:supported_version('fake-node2@localhost', api2)), diff --git a/apps/emqx/test/emqx_bpapi_static_checks.erl b/apps/emqx/test/emqx_bpapi_static_checks.erl index 657776317..6f6e5df49 100644 --- a/apps/emqx/test/emqx_bpapi_static_checks.erl +++ b/apps/emqx/test/emqx_bpapi_static_checks.erl @@ -16,7 +16,7 @@ -module(emqx_bpapi_static_checks). --export([run/0, dump/1, dump/0, check_compat/1, versions_file/0, dumps_dir/0]). +-export([run/0, dump/1, dump/0, check_compat/1, versions_file/0, dumps_dir/0, dump_file_extension/0]). %% Using an undocumented API here :( -include_lib("dialyzer/src/dialyzer.hrl"). @@ -90,7 +90,7 @@ run() -> case dump() of true -> - Dumps = filelib:wildcard(dumps_dir() ++ "/*.bpapi"), + Dumps = filelib:wildcard(dumps_dir() ++ "/*" ++ dump_file_extension()), case Dumps of [] -> logger:error("No BPAPI dumps are found in ~s, abort", [dumps_dir()]), @@ -293,7 +293,7 @@ prepare(#{reldir := RelDir, plt := PLT}) -> xref:add_release(?XREF, RelDir), %% Now to the dialyzer stuff: logger:info("Loading PLT...", []), - dialyzer_plt:from_file(PLT). + load_plt(PLT). %% erlfmt-ignore find_remote_calls(_Opts) -> @@ -331,7 +331,7 @@ is_bpapi_call({Module, _Function, _Arity}) -> -spec dump_api(fulldump()) -> ok. dump_api(Term = #{api := _, signatures := _, release := Release}) -> - Filename = filename:join(dumps_dir(), Release ++ ".bpapi"), + Filename = filename:join(dumps_dir(), Release ++ dump_file_extension()), ok = filelib:ensure_dir(Filename), file:write_file(Filename, io_lib:format("~0p.~n", [Term])). @@ -436,3 +436,18 @@ emqx_app_dir() -> project_root_dir() -> filename:dirname(filename:dirname(emqx_app_dir())). + +-if(?OTP_RELEASE >= 26). +load_plt(File) -> + dialyzer_cplt:from_file(File). + +dump_file_extension() -> + %% OTP26 changes the internal format for the types: + ".bpapi2". +-else. +load_plt(File) -> + dialyzer_plt:from_file(File). + +dump_file_extension() -> + ".bpapi". +-endif. diff --git a/apps/emqx/test/emqx_broker_SUITE.erl b/apps/emqx/test/emqx_broker_SUITE.erl index b416f1730..0325260ac 100644 --- a/apps/emqx/test/emqx_broker_SUITE.erl +++ b/apps/emqx/test/emqx_broker_SUITE.erl @@ -94,7 +94,7 @@ init_per_group(quic, Config) -> [ {conn_fun, quic_connect}, {port, emqx_config:get([listeners, quic, test, bind])}, - {ssl_opts, emqx_common_test_helpers:client_ssl_twoway()}, + {ssl_opts, emqx_common_test_helpers:client_mtls()}, {ssl, true}, {group_apps, Apps} | Config diff --git a/apps/emqx/test/emqx_channel_delayed_puback_SUITE.erl b/apps/emqx/test/emqx_channel_delayed_puback_SUITE.erl index 4f2938b24..da8f5d7a5 100644 --- a/apps/emqx/test/emqx_channel_delayed_puback_SUITE.erl +++ b/apps/emqx/test/emqx_channel_delayed_puback_SUITE.erl @@ -31,12 +31,11 @@ all() -> emqx_common_test_helpers:all(?MODULE). init_per_suite(Config) -> - emqx_common_test_helpers:boot_modules(all), - emqx_common_test_helpers:start_apps([]), - Config. + Apps = emqx_cth_suite:start([emqx], #{work_dir => emqx_cth_suite:work_dir(Config)}), + [{apps, Apps} | Config]. -end_per_suite(_Config) -> - emqx_common_test_helpers:stop_apps([]). +end_per_suite(Config) -> + emqx_cth_suite:stop(?config(apps, Config)). init_per_testcase(Case, Config) -> ?MODULE:Case({init, Config}). diff --git a/apps/emqx/test/emqx_client_SUITE.erl b/apps/emqx/test/emqx_client_SUITE.erl index c9923365e..bb4ef0826 100644 --- a/apps/emqx/test/emqx_client_SUITE.erl +++ b/apps/emqx/test/emqx_client_SUITE.erl @@ -83,14 +83,14 @@ groups() -> ]. init_per_suite(Config) -> - emqx_common_test_helpers:boot_modules(all), - emqx_common_test_helpers:start_apps([]), - emqx_config:put_listener_conf(ssl, default, [ssl_options, verify], verify_peer), - emqx_listeners:restart_listener('ssl:default'), - Config. + Apps = emqx_cth_suite:start( + [{emqx, "listeners.ssl.default.ssl_options.verify = verify_peer"}], + #{work_dir => emqx_cth_suite:work_dir(Config)} + ), + [{apps, Apps} | Config]. -end_per_suite(_Config) -> - emqx_common_test_helpers:stop_apps([]). +end_per_suite(Config) -> + emqx_cth_suite:stop(?config(apps, Config)). init_per_testcase(_Case, Config) -> Config. @@ -395,7 +395,7 @@ t_peercert_preserved_before_connected(_) -> ?HP_HIGHEST ), ClientId = atom_to_binary(?FUNCTION_NAME), - SslConf = emqx_common_test_helpers:client_ssl_twoway(default), + SslConf = emqx_common_test_helpers:client_mtls(default), {ok, Client} = emqtt:start_link([ {port, 8883}, {clientid, ClientId}, @@ -455,7 +455,7 @@ tls_certcn_as_clientid(TLSVsn) -> tls_certcn_as_clientid(TLSVsn, RequiredTLSVsn) -> CN = <<"Client">>, emqx_config:put_zone_conf(default, [mqtt, peer_cert_as_clientid], cn), - SslConf = emqx_common_test_helpers:client_ssl_twoway(TLSVsn), + SslConf = emqx_common_test_helpers:client_mtls(TLSVsn), {ok, Client} = emqtt:start_link([{port, 8883}, {ssl, true}, {ssl_opts, SslConf}]), {ok, _} = emqtt:connect(Client), #{clientinfo := #{clientid := CN}} = emqx_cm:get_chan_info(CN), diff --git a/apps/emqx/test/emqx_cm_SUITE.erl b/apps/emqx/test/emqx_cm_SUITE.erl index 9bfb4d5e7..7a7a989cd 100644 --- a/apps/emqx/test/emqx_cm_SUITE.erl +++ b/apps/emqx/test/emqx_cm_SUITE.erl @@ -19,7 +19,6 @@ -compile(export_all). -compile(nowarn_export_all). --include_lib("emqx/include/emqx.hrl"). -include_lib("emqx/include/emqx_cm.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("snabbkaffe/include/snabbkaffe.hrl"). @@ -54,12 +53,11 @@ suite() -> [{timetrap, {minutes, 2}}]. all() -> emqx_common_test_helpers:all(?MODULE). init_per_suite(Config) -> - emqx_common_test_helpers:boot_modules(all), - emqx_common_test_helpers:start_apps([]), - Config. + Apps = emqx_cth_suite:start([emqx], #{work_dir => emqx_cth_suite:work_dir(Config)}), + [{apps, Apps} | Config]. -end_per_suite(_Config) -> - emqx_common_test_helpers:stop_apps([]). +end_per_suite(Config) -> + emqx_cth_suite:stop(proplists:get_value(apps, Config)). %%-------------------------------------------------------------------- %% TODO: Add more test cases diff --git a/apps/emqx/test/emqx_cm_locker_SUITE.erl b/apps/emqx/test/emqx_cm_locker_SUITE.erl index 08192d98c..1ee46067e 100644 --- a/apps/emqx/test/emqx_cm_locker_SUITE.erl +++ b/apps/emqx/test/emqx_cm_locker_SUITE.erl @@ -24,12 +24,11 @@ all() -> emqx_common_test_helpers:all(?MODULE). init_per_suite(Config) -> - emqx_common_test_helpers:boot_modules(all), - emqx_common_test_helpers:start_apps([]), - Config. + Apps = emqx_cth_suite:start([emqx], #{work_dir => emqx_cth_suite:work_dir(Config)}), + [{apps, Apps} | Config]. -end_per_suite(_Config) -> - emqx_common_test_helpers:stop_apps([]). +end_per_suite(Config) -> + emqx_cth_suite:stop(proplists:get_value(apps, Config)). t_start_link(_) -> emqx_cm_locker:start_link(). diff --git a/apps/emqx/test/emqx_cm_registry_SUITE.erl b/apps/emqx/test/emqx_cm_registry_SUITE.erl index ee764a58f..c8c32a03d 100644 --- a/apps/emqx/test/emqx_cm_registry_SUITE.erl +++ b/apps/emqx/test/emqx_cm_registry_SUITE.erl @@ -28,12 +28,11 @@ all() -> emqx_common_test_helpers:all(?MODULE). init_per_suite(Config) -> - emqx_common_test_helpers:boot_modules(all), - emqx_common_test_helpers:start_apps([]), - Config. + Apps = emqx_cth_suite:start([emqx], #{work_dir => emqx_cth_suite:work_dir(Config)}), + [{apps, Apps} | Config]. -end_per_suite(_Config) -> - emqx_common_test_helpers:stop_apps([]). +end_per_suite(Config) -> + emqx_cth_suite:stop(proplists:get_value(apps, Config)). init_per_testcase(_TestCase, Config) -> Config. diff --git a/apps/emqx/test/emqx_common_test_helpers.erl b/apps/emqx/test/emqx_common_test_helpers.erl index 96fd83438..d9c9470eb 100644 --- a/apps/emqx/test/emqx_common_test_helpers.erl +++ b/apps/emqx/test/emqx_common_test_helpers.erl @@ -48,8 +48,10 @@ -export([ client_ssl/0, client_ssl/1, - client_ssl_twoway/0, - client_ssl_twoway/1, + client_mtls/0, + client_mtls/1, + ssl_verify_fun_allow_any_host/0, + ssl_verify_fun_allow_any_host_impl/3, ensure_mnesia_stopped/0, ensure_quic_listener/2, ensure_quic_listener/3, @@ -435,11 +437,11 @@ flush(Msgs) -> after 0 -> lists:reverse(Msgs) end. -client_ssl_twoway() -> - client_ssl_twoway(default). +client_mtls() -> + client_mtls(default). -client_ssl_twoway(TLSVsn) -> - client_certs() ++ ciphers(TLSVsn). +client_mtls(TLSVsn) -> + ssl_verify_fun_allow_any_host() ++ client_certs() ++ ciphers(TLSVsn). %% Paths prepended to cert filenames client_certs() -> diff --git a/apps/emqx/test/emqx_config_SUITE.erl b/apps/emqx/test/emqx_config_SUITE.erl index 3de081df8..6a49507a6 100644 --- a/apps/emqx/test/emqx_config_SUITE.erl +++ b/apps/emqx/test/emqx_config_SUITE.erl @@ -25,12 +25,21 @@ all() -> emqx_common_test_helpers:all(?MODULE). init_per_suite(Config) -> - emqx_common_test_helpers:boot_modules(all), - emqx_common_test_helpers:start_apps([]), - Config. + WorkDir = emqx_cth_suite:work_dir(Config), + Apps = emqx_cth_suite:start( + [ + {emqx, #{ + override_env => [ + {cluster_override_conf_file, filename:join(WorkDir, "cluster_override.conf")} + ] + }} + ], + #{work_dir => WorkDir} + ), + [{apps, Apps} | Config]. -end_per_suite(_Config) -> - emqx_common_test_helpers:stop_apps([]). +end_per_suite(Config) -> + emqx_cth_suite:stop(?config(apps, Config)). init_per_testcase(TestCase, Config) -> try diff --git a/apps/emqx/test/emqx_config_handler_SUITE.erl b/apps/emqx/test/emqx_config_handler_SUITE.erl index bb91bcbe4..b4f4085fe 100644 --- a/apps/emqx/test/emqx_config_handler_SUITE.erl +++ b/apps/emqx/test/emqx_config_handler_SUITE.erl @@ -30,12 +30,11 @@ all() -> emqx_common_test_helpers:all(?MODULE). init_per_suite(Config) -> - emqx_common_test_helpers:boot_modules(all), - emqx_common_test_helpers:start_apps([]), - Config. + Apps = emqx_cth_suite:start([emqx], #{work_dir => emqx_cth_suite:work_dir(Config)}), + [{apps, Apps} | Config]. -end_per_suite(_Config) -> - emqx_common_test_helpers:stop_apps([]). +end_per_suite(Config) -> + emqx_cth_suite:stop(?config(apps, Config)). init_per_testcase(_Case, Config) -> _ = file:delete(?CLUSTER_CONF), diff --git a/apps/emqx/test/emqx_connection_SUITE.erl b/apps/emqx/test/emqx_connection_SUITE.erl index 83f5bce0f..98d4e3102 100644 --- a/apps/emqx/test/emqx_connection_SUITE.erl +++ b/apps/emqx/test/emqx_connection_SUITE.erl @@ -57,10 +57,10 @@ init_per_suite(Config) -> ok = meck:expect(emqx_alarm, deactivate, fun(_) -> ok end), ok = meck:expect(emqx_alarm, deactivate, fun(_, _) -> ok end), - emqx_common_test_helpers:start_apps([]), - Config. + Apps = emqx_cth_suite:start([emqx], #{work_dir => emqx_cth_suite:work_dir(Config)}), + [{apps, Apps} | Config]. -end_per_suite(_Config) -> +end_per_suite(Config) -> ok = meck:unload(emqx_transport), catch meck:unload(emqx_channel), ok = meck:unload(emqx_cm), @@ -68,8 +68,8 @@ end_per_suite(_Config) -> ok = meck:unload(emqx_metrics), ok = meck:unload(emqx_hooks), ok = meck:unload(emqx_alarm), - emqx_common_test_helpers:stop_apps([]), - ok. + + emqx_cth_suite:stop(proplists:get_value(apps, Config)). init_per_testcase(TestCase, Config) when TestCase =/= t_ws_pingreq_before_connected diff --git a/apps/emqx/test/emqx_crl_cache_SUITE.erl b/apps/emqx/test/emqx_crl_cache_SUITE.erl index 806a120aa..36883b182 100644 --- a/apps/emqx/test/emqx_crl_cache_SUITE.erl +++ b/apps/emqx/test/emqx_crl_cache_SUITE.erl @@ -7,7 +7,8 @@ -compile(export_all). -compile(nowarn_export_all). --include_lib("eunit/include/eunit.hrl"). +-include_lib("stdlib/include/assert.hrl"). +-include_lib("emqx/include/asserts.hrl"). -include_lib("common_test/include/ct.hrl"). -include_lib("snabbkaffe/include/snabbkaffe.hrl"). @@ -34,14 +35,9 @@ all() -> emqx_common_test_helpers:all(?MODULE). init_per_suite(Config) -> - application:load(emqx), - {ok, _} = application:ensure_all_started(ssl), - emqx_config:save_schema_mod_and_names(emqx_schema), - emqx_common_test_helpers:boot_modules(all), Config. end_per_suite(_Config) -> - emqx_config:erase_all(), ok. init_per_testcase(TestCase, Config) when @@ -50,76 +46,78 @@ init_per_testcase(TestCase, Config) when TestCase =:= t_revoked -> ct:timetrap({seconds, 30}), - DataDir = ?config(data_dir, Config), - CRLFile = filename:join([DataDir, "intermediate-revoked.crl.pem"]), - {ok, CRLPem} = file:read_file(CRLFile), - [{'CertificateList', CRLDer, not_encrypted}] = public_key:pem_decode(CRLPem), ok = snabbkaffe:start_trace(), + DataDir = ?config(data_dir, Config), + {CRLPem, CRLDer} = read_crl(filename:join(DataDir, "intermediate-revoked.crl.pem")), ServerPid = start_crl_server(CRLPem), IsCached = lists:member(TestCase, [t_filled_cache, t_revoked]), - ok = setup_crl_options(Config, #{is_cached => IsCached}), + Apps = start_emqx_with_crl_cache(#{is_cached => IsCached}, TestCase, Config), [ {crl_pem, CRLPem}, {crl_der, CRLDer}, - {http_server, ServerPid} + {http_server, ServerPid}, + {tc_apps, Apps} | Config ]; -init_per_testcase(t_revoke_then_refresh, Config) -> +init_per_testcase(t_revoke_then_refresh = TestCase, Config) -> ct:timetrap({seconds, 120}), - DataDir = ?config(data_dir, Config), - CRLFileNotRevoked = filename:join([DataDir, "intermediate-not-revoked.crl.pem"]), - {ok, CRLPemNotRevoked} = file:read_file(CRLFileNotRevoked), - [{'CertificateList', CRLDerNotRevoked, not_encrypted}] = public_key:pem_decode( - CRLPemNotRevoked - ), - CRLFileRevoked = filename:join([DataDir, "intermediate-revoked.crl.pem"]), - {ok, CRLPemRevoked} = file:read_file(CRLFileRevoked), - [{'CertificateList', CRLDerRevoked, not_encrypted}] = public_key:pem_decode(CRLPemRevoked), ok = snabbkaffe:start_trace(), + DataDir = ?config(data_dir, Config), + {CRLPemNotRevoked, CRLDerNotRevoked} = + read_crl(filename:join(DataDir, "intermediate-not-revoked.crl.pem")), + {CRLPemRevoked, CRLDerRevoked} = + read_crl(filename:join(DataDir, "intermediate-revoked.crl.pem")), ServerPid = start_crl_server(CRLPemNotRevoked), - ExtraVars = #{refresh_interval => <<"10s">>}, - ok = setup_crl_options(Config, #{is_cached => true, extra_vars => ExtraVars}), + Apps = start_emqx_with_crl_cache( + #{is_cached => true, overrides => #{crl_cache => #{refresh_interval => <<"10s">>}}}, + TestCase, + Config + ), [ {crl_pem_not_revoked, CRLPemNotRevoked}, {crl_der_not_revoked, CRLDerNotRevoked}, {crl_pem_revoked, CRLPemRevoked}, {crl_der_revoked, CRLDerRevoked}, - {http_server, ServerPid} + {http_server, ServerPid}, + {tc_apps, Apps} | Config ]; -init_per_testcase(t_cache_overflow, Config) -> +init_per_testcase(t_cache_overflow = TestCase, Config) -> ct:timetrap({seconds, 120}), - DataDir = ?config(data_dir, Config), - CRLFileRevoked = filename:join([DataDir, "intermediate-revoked.crl.pem"]), - {ok, CRLPemRevoked} = file:read_file(CRLFileRevoked), ok = snabbkaffe:start_trace(), + DataDir = ?config(data_dir, Config), + {CRLPemRevoked, _} = read_crl(filename:join(DataDir, "intermediate-revoked.crl.pem")), ServerPid = start_crl_server(CRLPemRevoked), - ExtraVars = #{cache_capacity => <<"2">>}, - ok = setup_crl_options(Config, #{is_cached => false, extra_vars => ExtraVars}), + Apps = start_emqx_with_crl_cache( + #{is_cached => false, overrides => #{crl_cache => #{capacity => 2}}}, + TestCase, + Config + ), [ - {http_server, ServerPid} + {http_server, ServerPid}, + {tc_apps, Apps} | Config ]; -init_per_testcase(t_not_cached_and_unreachable, Config) -> +init_per_testcase(TestCase, Config) when + TestCase =:= t_not_cached_and_unreachable; + TestCase =:= t_update_config +-> ct:timetrap({seconds, 30}), - DataDir = ?config(data_dir, Config), - CRLFile = filename:join([DataDir, "intermediate-revoked.crl.pem"]), - {ok, CRLPem} = file:read_file(CRLFile), - [{'CertificateList', CRLDer, not_encrypted}] = public_key:pem_decode(CRLPem), ok = snabbkaffe:start_trace(), - application:stop(cowboy), - ok = setup_crl_options(Config, #{is_cached => false}), + DataDir = ?config(data_dir, Config), + {CRLPem, CRLDer} = read_crl(filename:join(DataDir, "intermediate-revoked.crl.pem")), + Apps = start_emqx_with_crl_cache(#{is_cached => false}, TestCase, Config), [ {crl_pem, CRLPem}, - {crl_der, CRLDer} + {crl_der, CRLDer}, + {tc_apps, Apps} | Config ]; -init_per_testcase(t_refresh_config, Config) -> +init_per_testcase(t_refresh_config = TestCase, Config) -> ct:timetrap({seconds, 30}), + ok = snabbkaffe:start_trace(), DataDir = ?config(data_dir, Config), - CRLFile = filename:join([DataDir, "intermediate-revoked.crl.pem"]), - {ok, CRLPem} = file:read_file(CRLFile), - [{'CertificateList', CRLDer, not_encrypted}] = public_key:pem_decode(CRLPem), + {CRLPem, CRLDer} = read_crl(filename:join(DataDir, "intermediate-revoked.crl.pem")), TestPid = self(), ok = meck:new(emqx_crl_cache, [non_strict, passthrough, no_history, no_link]), meck:expect( @@ -131,42 +129,49 @@ init_per_testcase(t_refresh_config, Config) -> {ok, {{"HTTP/1.0", 200, "OK"}, [], CRLPem}} end ), - ok = snabbkaffe:start_trace(), - ok = setup_crl_options(Config, #{is_cached => false}), + Apps = start_emqx_with_crl_cache(#{is_cached => false}, TestCase, Config), [ {crl_pem, CRLPem}, - {crl_der, CRLDer} + {crl_der, CRLDer}, + {tc_apps, Apps} | Config ]; init_per_testcase(TestCase, Config) when TestCase =:= t_update_listener; TestCase =:= t_validations -> + ct:timetrap({seconds, 30}), + ok = snabbkaffe:start_trace(), %% when running emqx standalone tests, we can't use those %% features. - case does_module_exist(emqx_mgmt_api_test_util) of + case does_module_exist(emqx_management) of true -> - ct:timetrap({seconds, 30}), DataDir = ?config(data_dir, Config), - PrivDir = ?config(priv_dir, Config), CRLFile = filename:join([DataDir, "intermediate-revoked.crl.pem"]), {ok, CRLPem} = file:read_file(CRLFile), - ok = snabbkaffe:start_trace(), ServerPid = start_crl_server(CRLPem), - ConfFilePath = filename:join([DataDir, "emqx_just_verify.conf"]), - emqx_mgmt_api_test_util:init_suite( - [emqx_conf], - fun emqx_mgmt_api_test_util:set_special_configs/1, - #{ - extra_mustache_vars => #{ - test_data_dir => DataDir, - test_priv_dir => PrivDir - }, - conf_file_path => ConfFilePath + ListenerConf = #{ + enable => true, + ssl_options => #{ + keyfile => filename:join(DataDir, "server.key.pem"), + certfile => filename:join(DataDir, "server.cert.pem"), + cacertfile => filename:join(DataDir, "ca-chain.cert.pem"), + verify => verify_peer, + enable_crl_check => false } + }, + Apps = emqx_cth_suite:start( + [ + {emqx_conf, #{config => #{listeners => #{ssl => #{default => ListenerConf}}}}}, + emqx, + emqx_management, + {emqx_dashboard, "dashboard.listeners.http { enable = true, bind = 18083 }"} + ], + #{work_dir => emqx_cth_suite:work_dir(TestCase, Config)} ), [ - {http_server, ServerPid} + {http_server, ServerPid}, + {tc_apps, Apps} | Config ]; false -> @@ -174,10 +179,9 @@ init_per_testcase(TestCase, Config) when end; init_per_testcase(_TestCase, Config) -> ct:timetrap({seconds, 30}), + ok = snabbkaffe:start_trace(), DataDir = ?config(data_dir, Config), - CRLFile = filename:join([DataDir, "intermediate-revoked.crl.pem"]), - {ok, CRLPem} = file:read_file(CRLFile), - [{'CertificateList', CRLDer, not_encrypted}] = public_key:pem_decode(CRLPem), + {CRLPem, CRLDer} = read_crl(filename:join(DataDir, "intermediate-revoked.crl.pem")), TestPid = self(), ok = meck:new(emqx_crl_cache, [non_strict, passthrough, no_history, no_link]), meck:expect( @@ -189,53 +193,17 @@ init_per_testcase(_TestCase, Config) -> {ok, {{"HTTP/1.0", 200, 'OK'}, [], CRLPem}} end ), - ok = snabbkaffe:start_trace(), [ {crl_pem, CRLPem}, {crl_der, CRLDer} | Config ]. -end_per_testcase(TestCase, Config) when - TestCase =:= t_cache; - TestCase =:= t_filled_cache; - TestCase =:= t_revoked --> - ServerPid = ?config(http_server, Config), - emqx_crl_cache_http_server:stop(ServerPid), - emqx_common_test_helpers:stop_apps([]), - clear_listeners(), - application:stop(cowboy), - clear_crl_cache(), - ok = snabbkaffe:stop(), - ok; -end_per_testcase(TestCase, Config) when - TestCase =:= t_revoke_then_refresh; - TestCase =:= t_cache_overflow --> - ServerPid = ?config(http_server, Config), - emqx_crl_cache_http_server:stop(ServerPid), - emqx_common_test_helpers:stop_apps([]), - clear_listeners(), - clear_crl_cache(), - application:stop(cowboy), - ok = snabbkaffe:stop(), - ok; -end_per_testcase(t_not_cached_and_unreachable, _Config) -> - emqx_common_test_helpers:stop_apps([]), - clear_listeners(), - clear_crl_cache(), - ok = snabbkaffe:stop(), - ok; -end_per_testcase(t_refresh_config, _Config) -> - meck:unload([emqx_crl_cache]), - clear_crl_cache(), - emqx_common_test_helpers:stop_apps([]), - clear_listeners(), - clear_crl_cache(), - application:stop(cowboy), - ok = snabbkaffe:stop(), - ok; +read_crl(Filename) -> + {ok, PEM} = file:read_file(Filename), + [{'CertificateList', DER, not_encrypted}] = public_key:pem_decode(PEM), + {PEM, DER}. + end_per_testcase(TestCase, Config) when TestCase =:= t_update_listener; TestCase =:= t_validations @@ -245,18 +213,20 @@ end_per_testcase(TestCase, Config) when true -> ok; false -> - ServerPid = ?config(http_server, Config), - emqx_crl_cache_http_server:stop(ServerPid), - emqx_mgmt_api_test_util:end_suite([emqx_conf]), - clear_listeners(), - ok = snabbkaffe:stop(), - clear_crl_cache(), - ok + end_per_testcase(common, Config) end; -end_per_testcase(_TestCase, _Config) -> - meck:unload([emqx_crl_cache]), - clear_crl_cache(), +end_per_testcase(_TestCase, Config) -> ok = snabbkaffe:stop(), + clear_crl_cache(), + _ = emqx_maybe:apply( + fun emqx_crl_cache_http_server:stop/1, + proplists:get_value(http_server, Config) + ), + _ = emqx_maybe:apply( + fun emqx_cth_suite:stop/1, + proplists:get_value(tc_apps, Config) + ), + catch meck:unload([emqx_crl_cache]), ok. %%-------------------------------------------------------------------- @@ -278,11 +248,6 @@ does_module_exist(Mod) -> end end. -clear_listeners() -> - emqx_config:put([listeners], #{}), - emqx_config:put_raw([<<"listeners">>], #{}), - ok. - assert_http_get(URL) -> receive {http_get, URL} -> @@ -341,61 +306,41 @@ clear_crl_cache() -> ensure_ssl_manager_alive(), ok. -force_cacertfile(Cacertfile) -> - {SSLListeners0, OtherListeners} = lists:partition( - fun(#{proto := Proto}) -> Proto =:= ssl end, - emqx:get_env(listeners) - ), - SSLListeners = - lists:map( - fun(Listener = #{opts := Opts0}) -> - SSLOpts0 = proplists:get_value(ssl_options, Opts0), - %% it injects some garbage... - SSLOpts1 = lists:keydelete(cacertfile, 1, lists:keydelete(cacertfile, 1, SSLOpts0)), - SSLOpts2 = [{cacertfile, Cacertfile} | SSLOpts1], - Opts1 = lists:keyreplace(ssl_options, 1, Opts0, {ssl_options, SSLOpts2}), - Listener#{opts => Opts1} - end, - SSLListeners0 - ), - application:set_env(emqx, listeners, SSLListeners ++ OtherListeners), - ok. - -setup_crl_options(Config, #{is_cached := IsCached} = Opts) -> +start_emqx_with_crl_cache(#{is_cached := IsCached} = Opts, TC, Config) -> DataDir = ?config(data_dir, Config), - ConfFilePath = filename:join([DataDir, "emqx.conf"]), - Defaults = #{ - refresh_interval => <<"11m">>, - cache_capacity => <<"100">>, - test_data_dir => DataDir - }, - ExtraVars0 = maps:get(extra_vars, Opts, #{}), - ExtraVars = maps:merge(Defaults, ExtraVars0), - emqx_common_test_helpers:start_apps( - [], - fun(_) -> ok end, - #{ - extra_mustache_vars => ExtraVars, - conf_file_path => ConfFilePath + Overrides = maps:get(overrides, Opts, #{}), + ListenerConf = #{ + enable => true, + ssl_options => #{ + keyfile => filename:join(DataDir, "server.key.pem"), + certfile => filename:join(DataDir, "server.cert.pem"), + cacertfile => filename:join(DataDir, "ca-chain.cert.pem"), + verify => verify_peer, + enable_crl_check => true } + }, + Conf = #{ + listeners => #{ssl => #{default => ListenerConf}}, + crl_cache => #{ + refresh_interval => <<"11m">>, + http_timeout => <<"17s">>, + capacity => 100 + } + }, + Apps = emqx_cth_suite:start( + [{emqx, #{config => emqx_utils_maps:deep_merge(Conf, Overrides)}}], + #{work_dir => emqx_cth_suite:work_dir(TC, Config)} ), case IsCached of true -> %% wait the cache to be filled emqx_crl_cache:refresh(?DEFAULT_URL), - receive - {http_get, <>} -> ok - after 1_000 -> - ct:pal("mailbox: ~p", [process_info(self(), messages)]), - error(crl_cache_not_filled) - end; + ?assertReceive({http_get, <>}); false -> %% ensure cache is empty - clear_crl_cache(), ok end, - drain_msgs(), - ok. + Apps. start_crl_server(CRLPem) -> application:ensure_all_started(cowboy), @@ -442,7 +387,8 @@ assert_successful_connection(Config, ClientNum) -> {ssl, true}, {ssl_opts, [ {certfile, ClientCert}, - {keyfile, ClientKey} + {keyfile, ClientKey}, + {verify, verify_none} ]}, {port, 8883} ]), @@ -494,31 +440,21 @@ t_init_empty_urls(_Config) -> ok. t_update_config(_Config) -> - emqx_config:save_schema_mod_and_names(emqx_schema), - emqx_config_handler:start_link(), - {ok, Pid} = emqx_crl_cache:start_link(), Conf = #{ - refresh_interval => <<"5m">>, - http_timeout => <<"10m">>, - capacity => 123 + <<"refresh_interval">> => <<"5m">>, + <<"http_timeout">> => <<"10m">>, + <<"capacity">> => 123 }, ?assertMatch({ok, _}, emqx:update_config([<<"crl_cache">>], Conf)), - State = sys:get_state(Pid), + State = emqx_crl_cache:info(), ?assertEqual( #{ refresh_interval => timer:minutes(5), http_timeout => timer:minutes(10), - capacity => 123 + cache_capacity => 123 }, - #{ - refresh_interval => element(3, State), - http_timeout => element(4, State), - capacity => element(7, State) - } - ), - emqx_config:erase(<<"crl_cache">>), - emqx_config_handler:stop(), - ok. + maps:with([refresh_interval, http_timeout, cache_capacity], State) + ). t_manual_refresh(Config) -> CRLDer = ?config(crl_der, Config), @@ -666,7 +602,8 @@ t_cache(Config) -> {ssl, true}, {ssl_opts, [ {certfile, ClientCert}, - {keyfile, ClientKey} + {keyfile, ClientKey}, + {verify, verify_none} ]}, {port, 8883} ]), @@ -684,7 +621,8 @@ t_cache(Config) -> {ssl, true}, {ssl_opts, [ {certfile, ClientCert}, - {keyfile, ClientKey} + {keyfile, ClientKey}, + {verify, verify_none} ]}, {port, 8883} ]), @@ -894,7 +832,8 @@ t_filled_cache(Config) -> {ssl, true}, {ssl_opts, [ {certfile, ClientCert}, - {keyfile, ClientKey} + {keyfile, ClientKey}, + {verify, verify_none} ]}, {port, 8883} ]), @@ -918,7 +857,8 @@ t_not_cached_and_unreachable(Config) -> {ssl, true}, {ssl_opts, [ {certfile, ClientCert}, - {keyfile, ClientKey} + {keyfile, ClientKey}, + {verify, verify_none} ]}, {port, 8883} ]), @@ -936,7 +876,8 @@ t_revoked(Config) -> {ssl, true}, {ssl_opts, [ {certfile, ClientCert}, - {keyfile, ClientKey} + {keyfile, ClientKey}, + {verify, verify_none} ]}, {port, 8883} ]), @@ -958,7 +899,8 @@ t_revoke_then_refresh(Config) -> {ssl, true}, {ssl_opts, [ {certfile, ClientCert}, - {keyfile, ClientKey} + {keyfile, ClientKey}, + {verify, verify_none} ]}, {port, 8883} ]), @@ -981,7 +923,8 @@ t_revoke_then_refresh(Config) -> {ssl, true}, {ssl_opts, [ {certfile, ClientCert}, - {keyfile, ClientKey} + {keyfile, ClientKey}, + {verify, verify_none} ]}, {port, 8883} ]), @@ -1026,7 +969,8 @@ do_t_update_listener(Config) -> {ssl, true}, {ssl_opts, [ {certfile, ClientCert}, - {keyfile, ClientKey} + {keyfile, ClientKey}, + {verify, verify_none} ]}, {port, 8883} ]), @@ -1064,7 +1008,8 @@ do_t_update_listener(Config) -> {ssl, true}, {ssl_opts, [ {certfile, ClientCert}, - {keyfile, ClientKey} + {keyfile, ClientKey}, + {verify, verify_none} ]}, {port, 8883} ]), diff --git a/apps/emqx/test/emqx_crl_cache_SUITE_data/emqx.conf b/apps/emqx/test/emqx_crl_cache_SUITE_data/emqx.conf deleted file mode 100644 index f34ab1456..000000000 --- a/apps/emqx/test/emqx_crl_cache_SUITE_data/emqx.conf +++ /dev/null @@ -1,12 +0,0 @@ -crl_cache.refresh_interval = {{ refresh_interval }} -crl_cache.http_timeout = 17s -crl_cache.capacity = {{ cache_capacity }} -listeners.ssl.default { - ssl_options { - keyfile = "{{ test_data_dir }}/server.key.pem" - certfile = "{{ test_data_dir }}/server.cert.pem" - cacertfile = "{{ test_data_dir }}/ca-chain.cert.pem" - verify = verify_peer - enable_crl_check = true - } -} diff --git a/apps/emqx/test/emqx_crl_cache_SUITE_data/emqx_just_verify.conf b/apps/emqx/test/emqx_crl_cache_SUITE_data/emqx_just_verify.conf deleted file mode 100644 index 8b9549823..000000000 --- a/apps/emqx/test/emqx_crl_cache_SUITE_data/emqx_just_verify.conf +++ /dev/null @@ -1,12 +0,0 @@ -node.name = test@127.0.0.1 -node.cookie = emqxsecretcookie -node.data_dir = "{{ test_priv_dir }}" -listeners.ssl.default { - ssl_options { - keyfile = "{{ test_data_dir }}/server.key.pem" - certfile = "{{ test_data_dir }}/server.cert.pem" - cacertfile = "{{ test_data_dir }}/ca-chain.cert.pem" - verify = verify_peer - enable_crl_check = false - } -} diff --git a/apps/emqx/test/emqx_exclusive_sub_SUITE.erl b/apps/emqx/test/emqx_exclusive_sub_SUITE.erl index 1caf4cc9b..a122c55e8 100644 --- a/apps/emqx/test/emqx_exclusive_sub_SUITE.erl +++ b/apps/emqx/test/emqx_exclusive_sub_SUITE.erl @@ -34,20 +34,14 @@ all() -> emqx_common_test_helpers:all(?MODULE). init_per_suite(Config) -> - emqx_common_test_helpers:boot_modules(all), - emqx_common_test_helpers:start_apps([]), - ok = ekka:start(), - OldConf = emqx:get_config([zones], #{}), - emqx_config:put_zone_conf(default, [mqtt, exclusive_subscription], true), - timer:sleep(50), - [{old_conf, OldConf} | Config]. + Apps = emqx_cth_suite:start( + [{emqx, "mqtt.exclusive_subscription = true"}], + #{work_dir => emqx_cth_suite:work_dir(Config)} + ), + [{apps, Apps} | Config]. end_per_suite(Config) -> - emqx_config:put([zones], proplists:get_value(old_conf, Config)), - ekka:stop(), - mria:stop(), - mria_mnesia:delete_schema(), - emqx_common_test_helpers:stop_apps([]). + emqx_cth_suite:stop(proplists:get_value(apps, Config)). end_per_testcase(_TestCase, _Config) -> emqx_exclusive_subscription:clear(). diff --git a/apps/emqx/test/emqx_listeners_update_SUITE.erl b/apps/emqx/test/emqx_listeners_update_SUITE.erl index c1fdff2e2..8ae9775a5 100644 --- a/apps/emqx/test/emqx_listeners_update_SUITE.erl +++ b/apps/emqx/test/emqx_listeners_update_SUITE.erl @@ -30,12 +30,11 @@ all() -> emqx_common_test_helpers:all(?MODULE). init_per_suite(Config) -> - emqx_common_test_helpers:boot_modules(all), - emqx_common_test_helpers:start_apps([]), - Config. + Apps = emqx_cth_suite:start([emqx], #{work_dir => emqx_cth_suite:work_dir(Config)}), + [{apps, Apps} | Config]. -end_per_suite(_Config) -> - emqx_common_test_helpers:stop_apps([]). +end_per_suite(Config) -> + emqx_cth_suite:stop(proplists:get_value(apps, Config)). init_per_testcase(_TestCase, Config) -> Init = emqx:get_raw_config(?LISTENERS), diff --git a/apps/emqx/test/emqx_ocsp_cache_SUITE.erl b/apps/emqx/test/emqx_ocsp_cache_SUITE.erl index fce74785c..ca0d191c4 100644 --- a/apps/emqx/test/emqx_ocsp_cache_SUITE.erl +++ b/apps/emqx/test/emqx_ocsp_cache_SUITE.erl @@ -915,10 +915,8 @@ do_t_validations(_Config) -> #{<<"code">> := <<"BAD_REQUEST">>, <<"message">> := MsgRaw3} = emqx_utils_json:decode(ResRaw3, [return_maps]), %% we can't remove certfile now, because it has default value. - ?assertMatch( - <<"{bad_ssl_config,#{file_read => enoent,pem_check => invalid_pem", _/binary>>, - MsgRaw3 - ), + ?assertMatch({match, _}, re:run(MsgRaw3, <<"enoent">>)), + ?assertMatch({match, _}, re:run(MsgRaw3, <<"invalid_pem">>)), ok. t_unknown_error_fetching_ocsp_response(_Config) -> diff --git a/apps/emqx/test/emqx_olp_SUITE.erl b/apps/emqx/test/emqx_olp_SUITE.erl index 7389b259c..2c418ebdf 100644 --- a/apps/emqx/test/emqx_olp_SUITE.erl +++ b/apps/emqx/test/emqx_olp_SUITE.erl @@ -35,8 +35,6 @@ end_per_suite(Config) -> emqx_cth_suite:stop(?config(apps, Config)). init_per_testcase(_, Config) -> - emqx_common_test_helpers:boot_modules(all), - emqx_common_test_helpers:start_apps([]), emqx_olp:enable(), case wait_for(fun() -> lc_sup:whereis_runq_flagman() end, 10) of true -> ok; diff --git a/apps/emqx/test/emqx_persistent_messages_SUITE.erl b/apps/emqx/test/emqx_persistent_messages_SUITE.erl index ff0f2733f..f25f38098 100644 --- a/apps/emqx/test/emqx_persistent_messages_SUITE.erl +++ b/apps/emqx/test/emqx_persistent_messages_SUITE.erl @@ -258,6 +258,75 @@ t_qos0(_Config) -> emqtt:stop(Pub) end. +t_qos0_only_many_streams(_Config) -> + ClientId = <>, + Sub = connect(ClientId, true, 30), + Pub = connect(<>, true, 0), + [ConnPid] = emqx_cm:lookup_channels(ClientId), + try + {ok, _, [1]} = emqtt:subscribe(Sub, <<"t/#">>, qos1), + + [ + emqtt:publish(Pub, Topic, Payload, ?QOS_0) + || {Topic, Payload} <- [ + {<<"t/1">>, <<"foo">>}, + {<<"t/2">>, <<"bar">>}, + {<<"t/3">>, <<"baz">>} + ] + ], + ?assertMatch( + [_, _, _], + receive_messages(3) + ), + + Inflight0 = get_session_inflight(ConnPid), + + [ + emqtt:publish(Pub, Topic, Payload, ?QOS_0) + || {Topic, Payload} <- [ + {<<"t/2">>, <<"foo">>}, + {<<"t/2">>, <<"bar">>}, + {<<"t/1">>, <<"baz">>} + ] + ], + ?assertMatch( + [_, _, _], + receive_messages(3) + ), + + [ + emqtt:publish(Pub, Topic, Payload, ?QOS_0) + || {Topic, Payload} <- [ + {<<"t/3">>, <<"foo">>}, + {<<"t/3">>, <<"bar">>}, + {<<"t/2">>, <<"baz">>} + ] + ], + ?assertMatch( + [_, _, _], + receive_messages(3) + ), + + ?assertMatch( + #{pubranges := [_, _, _]}, + emqx_persistent_session_ds:print_session(ClientId) + ), + + Inflight1 = get_session_inflight(ConnPid), + + %% TODO: Kinda stupid way to verify that the runtime state is not growing. + ?assert( + erlang:external_size(Inflight1) - erlang:external_size(Inflight0) < 16, + Inflight1 + ) + after + emqtt:stop(Sub), + emqtt:stop(Pub) + end. + +get_session_inflight(ConnPid) -> + emqx_connection:info({channel, {session, inflight}}, sys:get_state(ConnPid)). + t_publish_as_persistent(_Config) -> Sub = connect(<>, true, 30), Pub = connect(<>, true, 30), @@ -343,8 +412,8 @@ consume(It) -> case emqx_ds:next(?PERSISTENT_MESSAGE_DB, It, 100) of {ok, _NIt, _Msgs = []} -> []; - {ok, NIt, Msgs} -> - Msgs ++ consume(NIt); + {ok, NIt, MsgsAndKeys} -> + [Msg || {_DSKey, Msg} <- MsgsAndKeys] ++ consume(NIt); {ok, end_of_stream} -> [] end. diff --git a/apps/emqx/test/emqx_persistent_session_SUITE.erl b/apps/emqx/test/emqx_persistent_session_SUITE.erl index b25c1c299..09cbf306d 100644 --- a/apps/emqx/test/emqx_persistent_session_SUITE.erl +++ b/apps/emqx/test/emqx_persistent_session_SUITE.erl @@ -115,7 +115,7 @@ init_per_group(quic, Config) -> [ {port, get_listener_port(quic, test)}, {conn_fun, quic_connect}, - {ssl_opts, emqx_common_test_helpers:client_ssl_twoway()}, + {ssl_opts, emqx_common_test_helpers:client_mtls()}, {ssl, true}, {group_apps, Apps} | Config diff --git a/apps/emqx/test/emqx_quic_multistreams_SUITE.erl b/apps/emqx/test/emqx_quic_multistreams_SUITE.erl index b2205a659..da1ee9191 100644 --- a/apps/emqx/test/emqx_quic_multistreams_SUITE.erl +++ b/apps/emqx/test/emqx_quic_multistreams_SUITE.erl @@ -144,19 +144,35 @@ groups() -> ]. init_per_suite(Config) -> - emqx_common_test_helpers:start_apps([]), - UdpPort = 14567, - start_emqx_quic(UdpPort), - %% Turn off force_shutdown policy. - ShutdownPolicy = emqx_config:get_zone_conf(default, [force_shutdown]), - ct:pal("force shutdown config: ~p", [ShutdownPolicy]), - emqx_config:put_zone_conf(default, [force_shutdown], ShutdownPolicy#{enable := false}), - [{shutdown_policy, ShutdownPolicy}, {port, UdpPort}, {pub_qos, 0}, {sub_qos, 0} | Config]. + Apps = start_emqx(Config), + [{port, 14567}, {pub_qos, 0}, {sub_qos, 0}, {apps, Apps} | Config]. end_per_suite(Config) -> - emqx_config:put_zone_conf(default, [force_shutdown], ?config(shutdown_policy, Config)), - emqx_common_test_helpers:stop_apps([]), - ok. + emqx_cth_suite:stop(?config(apps, Config)). + +start_emqx(Config) -> + emqx_cth_suite:start( + [mk_emqx_spec()], + #{work_dir => emqx_cth_suite:work_dir(Config)} + ). + +stop_emqx(Config) -> + emqx_cth_suite:stop(?config(apps, Config)). + +restart_emqx(Config) -> + ok = stop_emqx(Config), + emqx_cth_suite:start( + [mk_emqx_spec()], + #{work_dir => emqx_cth_suite:work_dir(Config), boot_type => restart} + ). + +mk_emqx_spec() -> + {emqx, + %% Turn off force_shutdown policy. + "force_shutdown.enable = false" + "\n listeners.quic.default {" + "\n enable = true, bind = 14567, acceptors = 16, idle_timeout_ms = 15000" + "\n }"}. init_per_group(pub_qos0, Config) -> [{pub_qos, 0} | Config]; @@ -190,11 +206,6 @@ init_per_group(_, Config) -> end_per_group(_, Config) -> Config. -init_per_testcase(_, Config) -> - emqx_common_test_helpers:start_apps([]), - start_emqx_quic(?config(port, Config)), - Config. - t_quic_sock(Config) -> Port = 4567, SslOpts = [ @@ -1582,9 +1593,13 @@ t_multi_streams_remote_shutdown(Config) -> {quic, _Conn, _Ctrlstream} = proplists:get_value(socket, emqtt:info(C)), - ok = stop_emqx(), - %% Client should be closed - assert_client_die(C, 100, 200). + ok = stop_emqx(Config), + try + %% Client should be closed + assert_client_die(C, 100, 200) + after + restart_emqx(Config) + end. t_multi_streams_remote_shutdown_with_reconnect(Config) -> erlang:process_flag(trap_exit, true), @@ -1636,10 +1651,8 @@ t_multi_streams_remote_shutdown_with_reconnect(Config) -> {quic, _Conn, _Ctrlstream} = proplists:get_value(socket, emqtt:info(C)), - ok = stop_emqx(), + _Apps = restart_emqx(Config), - timer:sleep(200), - start_emqx_quic(?config(port, Config)), ?assert(is_list(emqtt:info(C))), emqtt:stop(C). @@ -2028,16 +2041,6 @@ calc_pkt_id(1, Id) -> calc_pkt_id(2, Id) -> Id. --spec start_emqx_quic(inet:port_number()) -> ok. -start_emqx_quic(UdpPort) -> - emqx_common_test_helpers:start_apps([]), - application:ensure_all_started(quicer), - emqx_common_test_helpers:ensure_quic_listener(?MODULE, UdpPort). - --spec stop_emqx() -> ok. -stop_emqx() -> - emqx_common_test_helpers:stop_apps([]). - %% select a random port picked by OS -spec select_port() -> inet:port_number(). select_port() -> diff --git a/apps/emqx/test/emqx_ratelimiter_SUITE.erl b/apps/emqx/test/emqx_ratelimiter_SUITE.erl index f414c3759..29f268f7c 100644 --- a/apps/emqx/test/emqx_ratelimiter_SUITE.erl +++ b/apps/emqx/test/emqx_ratelimiter_SUITE.erl @@ -47,23 +47,23 @@ all() -> emqx_common_test_helpers:all(?MODULE). init_per_suite(Config) -> - load_conf(), - emqx_common_test_helpers:start_apps([?APP]), - Config. + Apps = emqx_cth_suite:start([emqx], #{work_dir => emqx_cth_suite:work_dir(Config)}), + ok = load_conf(), + [{apps, Apps} | Config]. -end_per_suite(_Config) -> - emqx_common_test_helpers:stop_apps([?APP]). +end_per_suite(Config) -> + emqx_cth_suite:stop(?config(apps, Config)). init_per_testcase(_TestCase, Config) -> - emqx_config:erase(limiter), - load_conf(), + ok = emqx_config:erase(limiter), + ok = load_conf(), Config. end_per_testcase(_TestCase, Config) -> Config. load_conf() -> - ok = emqx_common_test_helpers:load_config(emqx_limiter_schema, ?BASE_CONF). + emqx_common_test_helpers:load_config(emqx_limiter_schema, ?BASE_CONF). init_config() -> emqx_config:init_load(emqx_limiter_schema, ?BASE_CONF). diff --git a/apps/emqx/test/emqx_request_responser_SUITE.erl b/apps/emqx/test/emqx_request_responser_SUITE.erl index 2685b4ac3..299ebf854 100644 --- a/apps/emqx/test/emqx_request_responser_SUITE.erl +++ b/apps/emqx/test/emqx_request_responser_SUITE.erl @@ -22,12 +22,11 @@ -include_lib("common_test/include/ct.hrl"). init_per_suite(Config) -> - emqx_common_test_helpers:boot_modules(all), - emqx_common_test_helpers:start_apps([]), - Config. + Apps = emqx_cth_suite:start([emqx], #{work_dir => emqx_cth_suite:work_dir(Config)}), + [{apps, Apps} | Config]. -end_per_suite(_Config) -> - emqx_common_test_helpers:stop_apps([]). +end_per_suite(Config) -> + emqx_cth_suite:stop(?config(apps, Config)). all() -> emqx_common_test_helpers:all(?MODULE). diff --git a/apps/emqx/test/emqx_shared_sub_SUITE.erl b/apps/emqx/test/emqx_shared_sub_SUITE.erl index 8af3b2190..b732735bd 100644 --- a/apps/emqx/test/emqx_shared_sub_SUITE.erl +++ b/apps/emqx/test/emqx_shared_sub_SUITE.erl @@ -49,31 +49,11 @@ all() -> emqx_common_test_helpers:all(?SUITE). init_per_suite(Config) -> - DistPid = - case net_kernel:nodename() of - ignored -> - %% calling `net_kernel:start' without `epmd' - %% running will result in a failure. - emqx_common_test_helpers:start_epmd(), - {ok, Pid} = net_kernel:start(['master@127.0.0.1', longnames]), - ct:pal("start epmd, node name: ~p", [node()]), - Pid; - _ -> - undefined - end, - emqx_common_test_helpers:boot_modules(all), - emqx_common_test_helpers:start_apps([]), - [{dist_pid, DistPid} | Config]. + Apps = emqx_cth_suite:start([emqx], #{work_dir => emqx_cth_suite:work_dir(Config)}), + [{apps, Apps} | Config]. end_per_suite(Config) -> - DistPid = ?config(dist_pid, Config), - case DistPid of - Pid when is_pid(Pid) -> - net_kernel:stop(); - _ -> - ok - end, - emqx_common_test_helpers:stop_apps([]). + emqx_cth_suite:stop(?config(apps, Config)). init_per_testcase(Case, Config) -> try @@ -759,11 +739,16 @@ t_qos1_random_dispatch_if_all_members_are_down(Config) when is_list(Config) -> ?assert(is_process_alive(Pid2)), {ok, _} = emqtt:publish(ConnPub, Topic, <<"hello11">>, 1), - ct:sleep(100), - Msgs1 = emqx_mqueue:to_list(get_mqueue(Pid1)), - Msgs2 = emqx_mqueue:to_list(get_mqueue(Pid2)), - %% assert the message is in mqueue (because socket is closed) - ?assertMatch([#message{payload = <<"hello11">>}], Msgs1 ++ Msgs2), + ?retry( + 100, + 10, + begin + Msgs1 = emqx_mqueue:to_list(get_mqueue(Pid1)), + Msgs2 = emqx_mqueue:to_list(get_mqueue(Pid2)), + %% assert the message is in mqueue (because socket is closed) + ?assertMatch([#message{payload = <<"hello11">>}], Msgs1 ++ Msgs2) + end + ), emqtt:stop(ConnPub), ok. diff --git a/apps/emqx/test/emqx_static_checks.erl b/apps/emqx/test/emqx_static_checks.erl index ea221b2b8..ae539781d 100644 --- a/apps/emqx/test/emqx_static_checks.erl +++ b/apps/emqx/test/emqx_static_checks.erl @@ -62,7 +62,10 @@ t_run_check(_) -> error(version_mismatch) end, BpapiDumps = filelib:wildcard( - filename:join(emqx_bpapi_static_checks:dumps_dir(), "*.bpapi") + filename:join( + emqx_bpapi_static_checks:dumps_dir(), + "*" ++ emqx_bpapi_static_checks:dump_file_extension() + ) ), logger:info("Backplane API dump files: ~p", [BpapiDumps]), ?assert(emqx_bpapi_static_checks:check_compat(BpapiDumps)) diff --git a/apps/emqx/test/emqx_static_checks_data/5.0.bpapi b/apps/emqx/test/emqx_static_checks_data/5.0.bpapi deleted file mode 100644 index 040fbee19..000000000 --- a/apps/emqx/test/emqx_static_checks_data/5.0.bpapi +++ /dev/null @@ -1 +0,0 @@ -#{api => #{{emqx_gateway_cm,1} => #{calls => [{{emqx_gateway_cm_proto_v1,cast,['GwName','ClientId','ChanPid','Req']},{emqx_gateway_cm,do_cast,['GwName','ClientId','ChanPid','Req']}},{{emqx_gateway_cm_proto_v1,call,['GwName','ClientId','ChanPid','Req']},{emqx_gateway_cm,do_call,['GwName','ClientId','ChanPid','Req']}},{{emqx_gateway_cm_proto_v1,call,['GwName','ClientId','ChanPid','Req','Timeout']},{emqx_gateway_cm,do_call,['GwName','ClientId','ChanPid','Req','Timeout']}},{{emqx_gateway_cm_proto_v1,takeover_session,['GwName','ClientId','ChanPid']},{emqx_gateway_cm,do_takeover_session,['GwName','ClientId','ChanPid']}},{{emqx_gateway_cm_proto_v1,get_chann_conn_mod,['GwName','ClientId','ChanPid']},{emqx_gateway_cm,do_get_chann_conn_mod,['GwName','ClientId','ChanPid']}},{{emqx_gateway_cm_proto_v1,kick_session,['GwName','Action','ClientId','ChanPid']},{emqx_gateway_cm,do_kick_session,['GwName','Action','ClientId','ChanPid']}},{{emqx_gateway_cm_proto_v1,set_chan_stats,['GwName','ClientId','ChanPid','Stats']},{emqx_gateway_cm,do_set_chan_stats,['GwName','ClientId','ChanPid','Stats']}},{{emqx_gateway_cm_proto_v1,get_chan_stats,['GwName','ClientId','ChanPid']},{emqx_gateway_cm,do_get_chan_stats,['GwName','ClientId','ChanPid']}},{{emqx_gateway_cm_proto_v1,set_chan_info,['GwName','ClientId','ChanPid','Infos']},{emqx_gateway_cm,do_set_chan_info,['GwName','ClientId','ChanPid','Infos']}},{{emqx_gateway_cm_proto_v1,get_chan_info,['GwName','ClientId','ChanPid']},{emqx_gateway_cm,do_get_chan_info,['GwName','ClientId','ChanPid']}},{{emqx_gateway_cm_proto_v1,lookup_by_clientid,['Nodes','GwName','ClientId']},{emqx_gateway_cm,do_lookup_by_clientid,['GwName','ClientId']}}],casts => []},{emqx_authn,1} => #{calls => [{{emqx_authn_proto_v1,lookup_from_all_nodes,['Nodes','ChainName','AuthenticatorID']},{emqx_authn_api,lookup_from_local_node,['ChainName','AuthenticatorID']}}],casts => []},{emqx_bridge,4} => #{calls => [{{emqx_bridge_proto_v4,get_metrics_from_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_api,get_metrics_from_local_node,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v4,lookup_from_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_api,lookup_from_local_node,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v4,stop_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,stop,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v4,start_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,start,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v4,restart_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,restart,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v4,stop_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,stop,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v4,start_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,start,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v4,restart_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,restart,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v4,list_bridges_on_nodes,['Nodes']},{emqx_bridge,list,[]}}],casts => []},{emqx_gateway_api_listeners,1} => #{calls => [{{emqx_gateway_api_listeners_proto_v1,listeners_cluster_status,['Nodes','Listeners']},{emqx_gateway_api_listeners,do_listeners_cluster_status,['Listeners']}}],casts => []},{emqx_slow_subs,1} => #{calls => [{{emqx_slow_subs_proto_v1,get_history,['Nodes']},{emqx_slow_subs_api,get_history,[]}},{{emqx_slow_subs_proto_v1,clear_history,['Nodes']},{emqx_slow_subs,clear_history,[]}}],casts => []},{emqx_license,1} => #{calls => [{{emqx_license_proto_v1,remote_connection_counts,['Nodes']},{emqx_license_resources,local_connection_count,[]}}],casts => []},{emqx_exhook,1} => #{calls => [{{emqx_exhook_proto_v1,server_hooks_metrics,['Nodes','Name']},{emqx_exhook_mgr,server_hooks_metrics,['Name']}},{{emqx_exhook_proto_v1,server_info,['Nodes','Name']},{emqx_exhook_mgr,server_info,['Name']}},{{emqx_exhook_proto_v1,all_servers_info,['Nodes']},{emqx_exhook_mgr,all_servers_info,[]}}],casts => []},{emqx_cm,1} => #{calls => [{{emqx_cm_proto_v1,kick_session,['Action','ClientId','ChanPid']},{emqx_cm,do_kick_session,['Action','ClientId','ChanPid']}},{{emqx_cm_proto_v1,takeover_session,['ClientId','ChanPid']},{emqx_cm,takeover_session,['ClientId','ChanPid']}},{{emqx_cm_proto_v1,get_chann_conn_mod,['ClientId','ChanPid']},{emqx_cm,do_get_chann_conn_mod,['ClientId','ChanPid']}},{{emqx_cm_proto_v1,get_chan_info,['ClientId','ChanPid']},{emqx_cm,do_get_chan_info,['ClientId','ChanPid']}},{{emqx_cm_proto_v1,get_chan_stats,['ClientId','ChanPid']},{emqx_cm,do_get_chan_stats,['ClientId','ChanPid']}},{{emqx_cm_proto_v1,lookup_client,['Node','Key']},{emqx_cm,lookup_client,['Key']}},{{emqx_cm_proto_v1,kickout_client,['Node','ClientId']},{emqx_cm,kick_session,['ClientId']}}],casts => []},{emqx_license,2} => #{calls => [{{emqx_license_proto_v2,remote_connection_counts,['Nodes']},{emqx_license_resources,local_connection_count,[]}}],casts => []},{emqx_retainer,1} => #{calls => [{{emqx_retainer_proto_v1,wait_dispatch_complete,['Nodes','Timeout']},{emqx_retainer_dispatcher,wait_dispatch_complete,['Timeout']}}],casts => []},{emqx_node_rebalance,1} => #{calls => [{{emqx_node_rebalance_proto_v1,disconnected_session_counts,['Nodes']},{emqx_node_rebalance,disconnected_session_count,[]}},{{emqx_node_rebalance_proto_v1,disable_rebalance_agent,['Nodes','OwnerPid']},{emqx_node_rebalance_agent,disable,['OwnerPid']}},{{emqx_node_rebalance_proto_v1,enable_rebalance_agent,['Nodes','OwnerPid']},{emqx_node_rebalance_agent,enable,['OwnerPid']}},{{emqx_node_rebalance_proto_v1,session_counts,['Nodes']},{emqx_node_rebalance,session_count,[]}},{{emqx_node_rebalance_proto_v1,connection_counts,['Nodes']},{emqx_node_rebalance,connection_count,[]}},{{emqx_node_rebalance_proto_v1,evict_sessions,['Nodes','Count','RecipientNodes','ConnState']},{emqx_eviction_agent,evict_sessions,['Count','RecipientNodes','ConnState']}},{{emqx_node_rebalance_proto_v1,evict_connections,['Nodes','Count']},{emqx_eviction_agent,evict_connections,['Count']}},{{emqx_node_rebalance_proto_v1,available_nodes,['Nodes']},{emqx_node_rebalance,is_node_available,[]}}],casts => []},{emqx_broker,1} => #{calls => [{{emqx_broker_proto_v1,list_subscriptions_via_topic,['Node','Topic']},{emqx_broker,subscriptions_via_topic,['Topic']}},{{emqx_broker_proto_v1,list_client_subscriptions,['Node','ClientId']},{emqx_broker,subscriptions,['ClientId']}},{{emqx_broker_proto_v1,forward,['Node','Topic','Delivery']},{emqx_broker,dispatch,['Topic','Delivery']}}],casts => [{{emqx_broker_proto_v1,forward_async,['Node','Topic','Delivery']},{emqx_broker,dispatch,['Topic','Delivery']}}]},{emqx_topic_metrics,1} => #{calls => [{{emqx_topic_metrics_proto_v1,reset,['Nodes','Topic']},{emqx_topic_metrics,reset,['Topic']}},{{emqx_topic_metrics_proto_v1,reset,['Nodes']},{emqx_topic_metrics,reset,[]}},{{emqx_topic_metrics_proto_v1,metrics,['Nodes','Topic']},{emqx_topic_metrics,metrics,['Topic']}},{{emqx_topic_metrics_proto_v1,metrics,['Nodes']},{emqx_topic_metrics,metrics,[]}}],casts => []},{emqx_resource,1} => #{calls => [{{emqx_resource_proto_v1,reset_metrics,['ResId']},{emqx_resource,reset_metrics_local,['ResId']}},{{emqx_resource_proto_v1,remove,['ResId']},{emqx_resource,remove_local,['ResId']}},{{emqx_resource_proto_v1,recreate,['ResId','ResourceType','Config','Opts']},{emqx_resource,recreate_local,['ResId','ResourceType','Config','Opts']}},{{emqx_resource_proto_v1,create_dry_run,['ResourceType','Config']},{emqx_resource,create_dry_run_local,['ResourceType','Config']}},{{emqx_resource_proto_v1,create,['ResId','Group','ResourceType','Config','Opts']},{emqx_resource,create_local,['ResId','Group','ResourceType','Config','Opts']}}],casts => []},{emqx_bridge,1} => #{calls => [{{emqx_bridge_proto_v1,lookup_from_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_api,lookup_from_local_node,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v1,stop_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,stop,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v1,restart_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,restart,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v1,stop_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,stop,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v1,restart_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,restart,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v1,list_bridges,['Node']},{emqx_bridge,list,[]}}],casts => []},{emqx_mgmt_trace,1} => #{calls => [{{emqx_mgmt_trace_proto_v1,read_trace_file,['Node','Name','Position','Limit']},{emqx_mgmt_api_trace,read_trace_file,['Name','Position','Limit']}},{{emqx_mgmt_trace_proto_v1,trace_file,['Nodes','File']},{emqx_trace,trace_file,['File']}},{{emqx_mgmt_trace_proto_v1,get_trace_size,['Nodes']},{emqx_mgmt_api_trace,get_trace_size,[]}}],casts => []},{emqx_ft_storage_fs_reader,1} => #{calls => [{{emqx_ft_storage_fs_reader_proto_v1,read,['Node','Pid','Bytes']},{emqx_ft_storage_fs_reader,read,['Pid','Bytes']}}],casts => []},{emqx_bridge,2} => #{calls => [{{emqx_bridge_proto_v2,lookup_from_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_api,lookup_from_local_node,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v2,stop_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,stop,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v2,start_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,start,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v2,restart_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,restart,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v2,stop_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,stop,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v2,start_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,start,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v2,restart_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,restart,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v2,list_bridges,['Node']},{emqx_bridge,list,[]}}],casts => []},{emqx_eviction_agent,1} => #{calls => [{{emqx_eviction_agent_proto_v1,evict_session_channel,['Node','ClientId','ConnInfo','ClientInfo']},{emqx_eviction_agent,evict_session_channel,['ClientId','ConnInfo','ClientInfo']}}],casts => []},{emqx_node_rebalance_api,1} => #{calls => [{{emqx_node_rebalance_api_proto_v1,node_rebalance_stop,['Node']},{emqx_node_rebalance,stop,[]}},{{emqx_node_rebalance_api_proto_v1,node_rebalance_start,['Node','Opts']},{emqx_node_rebalance,start,['Opts']}},{{emqx_node_rebalance_api_proto_v1,node_rebalance_evacuation_stop,['Node']},{emqx_node_rebalance_evacuation,stop,[]}},{{emqx_node_rebalance_api_proto_v1,node_rebalance_evacuation_start,['Node','Opts']},{emqx_node_rebalance_evacuation,start,['Opts']}}],casts => []},{emqx,1} => #{calls => [{{emqx_proto_v1,delete_all_deactivated_alarms,['Node']},{emqx_alarm,delete_all_deactivated_alarms,[]}},{{emqx_proto_v1,deactivate_alarm,['Node','Name']},{emqx_alarm,deactivate,['Name']}},{{emqx_proto_v1,clean_pem_cache,['Node']},{ssl_pem_cache,clear,[]}},{{emqx_proto_v1,clean_authz_cache,['Node']},{emqx_authz_cache,drain_cache,[]}},{{emqx_proto_v1,clean_authz_cache,['Node','ClientId']},{emqx_authz_cache,drain_cache,['ClientId']}},{{emqx_proto_v1,get_metrics,['Node']},{emqx_metrics,all,[]}},{{emqx_proto_v1,get_stats,['Node']},{emqx_stats,getstats,[]}},{{emqx_proto_v1,get_alarms,['Node','Type']},{emqx_alarm,get_alarms,['Type']}},{{emqx_proto_v1,is_running,['Node']},{emqx,is_running,[]}}],casts => []},{emqx_shared_sub,1} => #{calls => [{{emqx_shared_sub_proto_v1,dispatch_with_ack,['Pid','Group','Topic','Msg','Timeout']},{emqx_shared_sub,do_dispatch_with_ack,['Pid','Group','Topic','Msg']}}],casts => [{{emqx_shared_sub_proto_v1,send,['Node','Pid','Topic','Msg']},{erlang,send,['Pid','Msg']}}]},{emqx_management,1} => #{calls => [{{emqx_management_proto_v1,get_full_config,['Node']},{emqx_mgmt_api_configs,get_full_config,[]}},{{emqx_management_proto_v1,call_client,['Node','ClientId','Req']},{emqx_mgmt,do_call_client,['ClientId','Req']}},{{emqx_management_proto_v1,unsubscribe,['Node','ClientId','Topic']},{emqx_mgmt,do_unsubscribe,['ClientId','Topic']}},{{emqx_management_proto_v1,subscribe,['Node','ClientId','TopicTables']},{emqx_mgmt,do_subscribe,['ClientId','TopicTables']}},{{emqx_management_proto_v1,list_listeners,['Node']},{emqx_mgmt_api_listeners,do_list_listeners,[]}},{{emqx_management_proto_v1,list_subscriptions,['Node']},{emqx_mgmt,do_list_subscriptions,[]}},{{emqx_management_proto_v1,broker_info,['Node']},{emqx_mgmt,broker_info,[]}},{{emqx_management_proto_v1,node_info,['Node']},{emqx_mgmt,node_info,[]}}],casts => []},{emqx_persistent_session,1} => #{calls => [{{emqx_persistent_session_proto_v1,resume_end,['Nodes','Pid','SessionID']},{emqx_session_router,resume_end,['Pid','SessionID']}},{{emqx_persistent_session_proto_v1,resume_begin,['Nodes','Pid','SessionID']},{emqx_session_router,resume_begin,['Pid','SessionID']}}],casts => []},{emqx_bridge,3} => #{calls => [{{emqx_bridge_proto_v3,lookup_from_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_api,lookup_from_local_node,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v3,stop_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,stop,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v3,start_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,start,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v3,restart_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,restart,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v3,stop_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,stop,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v3,start_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,start,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v3,restart_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,restart,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v3,list_bridges_on_nodes,['Nodes']},{emqx_bridge,list,[]}},{{emqx_bridge_proto_v3,list_bridges,['Node']},{emqx_bridge,list,[]}}],casts => []},{emqx_mgmt_api_plugins,1} => #{calls => [{{emqx_mgmt_api_plugins_proto_v1,ensure_action,['Name','Action']},{emqx_mgmt_api_plugins,ensure_action,['Name','Action']}},{{emqx_mgmt_api_plugins_proto_v1,delete_package,['Name']},{emqx_mgmt_api_plugins,delete_package,['Name']}},{{emqx_mgmt_api_plugins_proto_v1,describe_package,['Name']},{emqx_mgmt_api_plugins,describe_package,['Name']}},{{emqx_mgmt_api_plugins_proto_v1,install_package,['Filename','Bin']},{emqx_mgmt_api_plugins,install_package,['Filename','Bin']}},{{emqx_mgmt_api_plugins_proto_v1,get_plugins,[]},{emqx_mgmt_api_plugins,get_plugins,[]}}],casts => []},{emqx_mgmt_trace,2} => #{calls => [{{emqx_mgmt_trace_proto_v2,read_trace_file,['Node','Name','Position','Limit']},{emqx_mgmt_api_trace,read_trace_file,['Name','Position','Limit']}},{{emqx_mgmt_trace_proto_v2,trace_file_detail,['Nodes','File']},{emqx_trace,trace_file_detail,['File']}},{{emqx_mgmt_trace_proto_v2,trace_file,['Nodes','File']},{emqx_trace,trace_file,['File']}},{{emqx_mgmt_trace_proto_v2,get_trace_size,['Nodes']},{emqx_mgmt_api_trace,get_trace_size,[]}}],casts => []},{emqx_gateway_http,1} => #{calls => [{{emqx_gateway_http_proto_v1,get_cluster_status,['Nodes','GwName']},{emqx_gateway_http,gateway_status,['GwName']}}],casts => []},{emqx_node_rebalance_status,1} => #{calls => [{{emqx_node_rebalance_status_proto_v1,evacuation_status,['Nodes']},{emqx_node_rebalance_status,evacuation_status,[]}},{{emqx_node_rebalance_status_proto_v1,rebalance_status,['Nodes']},{emqx_node_rebalance_status,rebalance_status,[]}},{{emqx_node_rebalance_status_proto_v1,local_status,['Node']},{emqx_node_rebalance_status,local_status,[]}}],casts => []},{emqx_authz,1} => #{calls => [{{emqx_authz_proto_v1,lookup_from_all_nodes,['Nodes','Type']},{emqx_authz_api_sources,lookup_from_local_node,['Type']}}],casts => []},{emqx_plugins,1} => #{calls => [{{emqx_plugins_proto_v1,get_tar,['Node','NameVsn','Timeout']},{emqx_plugins,get_tar,['NameVsn']}}],casts => []},{emqx_ft_storage_exporter_fs,1} => #{calls => [{{emqx_ft_storage_exporter_fs_proto_v1,read_export_file,['Node','Filepath','CallerPid']},{emqx_ft_storage_exporter_fs_proxy,read_export_file_local,['Filepath','CallerPid']}},{{emqx_ft_storage_exporter_fs_proto_v1,list_exports,['Nodes','Query']},{emqx_ft_storage_exporter_fs_proxy,list_exports_local,['Query']}}],casts => []},{emqx_prometheus,1} => #{calls => [{{emqx_prometheus_proto_v1,stop,['Nodes']},{emqx_prometheus,do_stop,[]}},{{emqx_prometheus_proto_v1,start,['Nodes']},{emqx_prometheus,do_start,[]}}],casts => []},{emqx,2} => #{calls => [{{emqx_proto_v2,delete_all_deactivated_alarms,['Node']},{emqx_alarm,delete_all_deactivated_alarms,[]}},{{emqx_proto_v2,deactivate_alarm,['Node','Name']},{emqx_alarm,deactivate,['Name']}},{{emqx_proto_v2,clean_pem_cache,['Node']},{ssl_pem_cache,clear,[]}},{{emqx_proto_v2,clean_authz_cache,['Node']},{emqx_authz_cache,drain_cache,[]}},{{emqx_proto_v2,clean_authz_cache,['Node','ClientId']},{emqx_authz_cache,drain_cache,['ClientId']}},{{emqx_proto_v2,get_metrics,['Node']},{emqx_metrics,all,[]}},{{emqx_proto_v2,get_stats,['Node']},{emqx_stats,getstats,[]}},{{emqx_proto_v2,get_alarms,['Node','Type']},{emqx_alarm,get_alarms,['Type']}},{{emqx_proto_v2,are_running,['Nodes']},{emqx,is_running,[]}},{{emqx_proto_v2,is_running,['Node']},{emqx,is_running,[]}}],casts => []},{emqx_delayed,1} => #{calls => [{{emqx_delayed_proto_v1,delete_delayed_message,['Node','Id']},{emqx_delayed,delete_delayed_message,['Id']}},{{emqx_delayed_proto_v1,get_delayed_message,['Node','Id']},{emqx_delayed,get_delayed_message,['Id']}}],casts => []},{emqx_conf,2} => #{calls => [{{emqx_conf_proto_v2,get_override_config_file,['Nodes']},{emqx_conf_app,get_override_config_file,[]}},{{emqx_conf_proto_v2,reset,['Node','KeyPath','Opts']},{emqx,reset_config,['KeyPath','Opts']}},{{emqx_conf_proto_v2,reset,['KeyPath','Opts']},{emqx,reset_config,['KeyPath','Opts']}},{{emqx_conf_proto_v2,remove_config,['Node','KeyPath','Opts']},{emqx,remove_config,['KeyPath','Opts']}},{{emqx_conf_proto_v2,remove_config,['KeyPath','Opts']},{emqx,remove_config,['KeyPath','Opts']}},{{emqx_conf_proto_v2,update,['Node','KeyPath','UpdateReq','Opts']},{emqx,update_config,['KeyPath','UpdateReq','Opts']}},{{emqx_conf_proto_v2,update,['KeyPath','UpdateReq','Opts']},{emqx,update_config,['KeyPath','UpdateReq','Opts']}},{{emqx_conf_proto_v2,get_all,['KeyPath']},{emqx_conf,get_node_and_config,['KeyPath']}},{{emqx_conf_proto_v2,get_config,['Node','KeyPath','Default']},{emqx,get_config,['KeyPath','Default']}},{{emqx_conf_proto_v2,get_config,['Node','KeyPath']},{emqx,get_config,['KeyPath']}},{{emqx_conf_proto_v2,sync_data_from_node,['Node']},{emqx_conf_app,sync_data_from_node,[]}}],casts => []},{emqx_plugin_libs,1} => #{calls => [{{emqx_plugin_libs_proto_v1,get_metrics,['Node','HandlerName','MetricId']},{emqx_metrics_worker,get_metrics,['HandlerName','MetricId']}}],casts => []},{emqx_management,2} => #{calls => [{{emqx_management_proto_v2,get_full_config,['Node']},{emqx_mgmt_api_configs,get_full_config,[]}},{{emqx_management_proto_v2,call_client,['Node','ClientId','Req']},{emqx_mgmt,do_call_client,['ClientId','Req']}},{{emqx_management_proto_v2,unsubscribe,['Node','ClientId','Topic']},{emqx_mgmt,do_unsubscribe,['ClientId','Topic']}},{{emqx_management_proto_v2,subscribe,['Node','ClientId','TopicTables']},{emqx_mgmt,do_subscribe,['ClientId','TopicTables']}},{{emqx_management_proto_v2,list_listeners,['Node']},{emqx_mgmt_api_listeners,do_list_listeners,[]}},{{emqx_management_proto_v2,list_subscriptions,['Node']},{emqx_mgmt,do_list_subscriptions,[]}},{{emqx_management_proto_v2,broker_info,['Node']},{emqx_mgmt,broker_info,[]}},{{emqx_management_proto_v2,node_info,['Node']},{emqx_mgmt,node_info,[]}},{{emqx_management_proto_v2,unsubscribe_batch,['Node','ClientId','Topics']},{emqx_mgmt,do_unsubscribe_batch,['ClientId','Topics']}}],casts => []},{emqx_cm,2} => #{calls => [{{emqx_cm_proto_v2,kick_session,['Action','ClientId','ChanPid']},{emqx_cm,do_kick_session,['Action','ClientId','ChanPid']}},{{emqx_cm_proto_v2,takeover_finish,['ConnMod','ChanPid']},{emqx_cm,takeover_finish,['ConnMod','ChanPid']}},{{emqx_cm_proto_v2,takeover_session,['ClientId','ChanPid']},{emqx_cm,takeover_session,['ClientId','ChanPid']}},{{emqx_cm_proto_v2,get_chann_conn_mod,['ClientId','ChanPid']},{emqx_cm,do_get_chann_conn_mod,['ClientId','ChanPid']}},{{emqx_cm_proto_v2,get_chan_info,['ClientId','ChanPid']},{emqx_cm,do_get_chan_info,['ClientId','ChanPid']}},{{emqx_cm_proto_v2,get_chan_stats,['ClientId','ChanPid']},{emqx_cm,do_get_chan_stats,['ClientId','ChanPid']}},{{emqx_cm_proto_v2,lookup_client,['Node','Key']},{emqx_cm,lookup_client,['Key']}},{{emqx_cm_proto_v2,kickout_client,['Node','ClientId']},{emqx_cm,kick_session,['ClientId']}}],casts => []},{emqx_conf,1} => #{calls => [{{emqx_conf_proto_v1,get_override_config_file,['Nodes']},{emqx_conf_app,get_override_config_file,[]}},{{emqx_conf_proto_v1,reset,['Node','KeyPath','Opts']},{emqx,reset_config,['KeyPath','Opts']}},{{emqx_conf_proto_v1,reset,['KeyPath','Opts']},{emqx,reset_config,['KeyPath','Opts']}},{{emqx_conf_proto_v1,remove_config,['Node','KeyPath','Opts']},{emqx,remove_config,['KeyPath','Opts']}},{{emqx_conf_proto_v1,remove_config,['KeyPath','Opts']},{emqx,remove_config,['KeyPath','Opts']}},{{emqx_conf_proto_v1,update,['Node','KeyPath','UpdateReq','Opts']},{emqx,update_config,['KeyPath','UpdateReq','Opts']}},{{emqx_conf_proto_v1,update,['KeyPath','UpdateReq','Opts']},{emqx,update_config,['KeyPath','UpdateReq','Opts']}},{{emqx_conf_proto_v1,get_all,['KeyPath']},{emqx_conf,get_node_and_config,['KeyPath']}},{{emqx_conf_proto_v1,get_config,['Node','KeyPath','Default']},{emqx,get_config,['KeyPath','Default']}},{{emqx_conf_proto_v1,get_config,['Node','KeyPath']},{emqx,get_config,['KeyPath']}}],casts => []},{emqx_ft_storage_fs,1} => #{calls => [{{emqx_ft_storage_fs_proto_v1,list_assemblers,['Nodes','Transfer']},{emqx_ft_storage_fs_proxy,lookup_local_assembler,['Transfer']}},{{emqx_ft_storage_fs_proto_v1,pread,['Node','Transfer','Frag','Offset','Size']},{emqx_ft_storage_fs_proxy,pread_local,['Transfer','Frag','Offset','Size']}},{{emqx_ft_storage_fs_proto_v1,multilist,['Nodes','Transfer','What']},{emqx_ft_storage_fs_proxy,list_local,['Transfer','What']}}],casts => []},{emqx_mgmt_cluster,1} => #{calls => [{{emqx_mgmt_cluster_proto_v1,invite_node,['Node','Self']},{emqx_mgmt_api_cluster,join,['Self']}}],casts => []},{emqx_management,3} => #{calls => [{{emqx_management_proto_v3,get_full_config,['Node']},{emqx_mgmt_api_configs,get_full_config,[]}},{{emqx_management_proto_v3,call_client,['Node','ClientId','Req']},{emqx_mgmt,do_call_client,['ClientId','Req']}},{{emqx_management_proto_v3,unsubscribe,['Node','ClientId','Topic']},{emqx_mgmt,do_unsubscribe,['ClientId','Topic']}},{{emqx_management_proto_v3,subscribe,['Node','ClientId','TopicTables']},{emqx_mgmt,do_subscribe,['ClientId','TopicTables']}},{{emqx_management_proto_v3,list_listeners,['Node']},{emqx_mgmt_api_listeners,do_list_listeners,[]}},{{emqx_management_proto_v3,list_subscriptions,['Node']},{emqx_mgmt,do_list_subscriptions,[]}},{{emqx_management_proto_v3,broker_info,['Nodes']},{emqx_mgmt,broker_info,[]}},{{emqx_management_proto_v3,node_info,['Nodes']},{emqx_mgmt,node_info,[]}},{{emqx_management_proto_v3,unsubscribe_batch,['Node','ClientId','Topics']},{emqx_mgmt,do_unsubscribe_batch,['ClientId','Topics']}}],casts => []},{emqx_telemetry,1} => #{calls => [{{emqx_telemetry_proto_v1,get_cluster_uuid,['Node']},{emqx_telemetry,get_cluster_uuid,[]}},{{emqx_telemetry_proto_v1,get_node_uuid,['Node']},{emqx_telemetry,get_node_uuid,[]}}],casts => []},{emqx_node_rebalance_evacuation,1} => #{calls => [{{emqx_node_rebalance_evacuation_proto_v1,available_nodes,['Nodes']},{emqx_node_rebalance_evacuation,is_node_available,[]}}],casts => []},{emqx_retainer,2} => #{calls => [{{emqx_retainer_proto_v2,active_mnesia_indices,['Nodes']},{emqx_retainer_mnesia,active_indices,[]}},{{emqx_retainer_proto_v2,wait_dispatch_complete,['Nodes','Timeout']},{emqx_retainer_dispatcher,wait_dispatch_complete,['Timeout']}}],casts => []},{emqx_rule_engine,1} => #{calls => [{{emqx_rule_engine_proto_v1,reset_metrics,['RuleId']},{emqx_rule_engine,reset_metrics_for_rule,['RuleId']}}],casts => []},{emqx_dashboard,1} => #{calls => [{{emqx_dashboard_proto_v1,current_rate,['Node']},{emqx_dashboard_monitor,current_rate,['Node']}},{{emqx_dashboard_proto_v1,do_sample,['Node','Latest']},{emqx_dashboard_monitor,do_sample,['Node','Latest']}}],casts => []}},release => "5.0",signatures => #{{emqx_bridge_proto_v2,stop_bridges_to_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_conf_proto_v1,remove_config,2} => {any,[{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_alarm,deactivate,1} => {any,[any]},{emqx_cm,do_get_chan_info,2} => {any,[any,any]},{emqx_ft_storage_fs_proxy,pread_local,4} => {any,[any,any,any,any]},{emqx_node_rebalance_status,evacuation_status,0} => {{c,tuple,[{c,atom,any,unknown},{c,union,[{c,atom,[disabled],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[enabled],unknown},{c,map,{[{{c,atom,[conn_evict_rate],unknown},mandatory,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[current_conns],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[current_sessions],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[initial_conns],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[initial_sessions],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[migrate_to],unknown},mandatory,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}},{{c,atom,[server_reference],unknown},mandatory,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}},{{c,atom,[sess_evict_rate],unknown},mandatory,{c,number,{int_rng,1,pos_inf},integer}}],none,none},unknown}],{2,{c,atom,[enabled],unknown}}},none,none,none],unknown}],{2,any}},[]},{emqx_bridge_proto_v4,start_bridges_to_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_cm_proto_v1,lookup_client,2} => {any,[{c,atom,any,unknown},{c,tuple_set,[{2,[{c,tuple,[{c,atom,[clientid],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}],{2,{c,atom,[clientid],unknown}}},{c,tuple,[{c,atom,[username],unknown},{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}],{2,{c,atom,[username],unknown}}}]}],unknown}]},{emqx_bridge_proto_v3,stop_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_conf_proto_v1,update,3} => {any,[{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},any,{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_plugins,get_tar,1} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,binary,[8,0],unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},{c,number,{int_rng,0,1114111},integer},none,none,none,none],unknown}]},{emqx_broker,subscriptions_via_topic,1} => {{c,list,[any,{c,nil,[],unknown}],unknown},[any]},{emqx_cm,takeover_session,2} => {{c,union,[{c,atom,any,unknown},none,none,none,{c,list,[{c,tuple,[{c,atom,any,unknown},any],{2,any}},{c,nil,[],unknown}],unknown},none,{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[expired],unknown},{c,tuple,[{c,atom,[session],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,binary,[0,128],unknown},{c,atom,[false,true],unknown},{c,map,{[],any,any},unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown},{c,atom,[false,true],unknown},{c,opaque,[{opaque,emqx_inflight,inflight,[],{c,tuple,[any,any,any],{3,any}}}],unknown},{c,tuple,[any,any,any,any,any,any,any,any,any,any,any],{11,any}},{c,number,{int_rng,1,1114111},integer},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown},{c,map,{[],any,any},unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown},{c,number,{int_rng,1,pos_inf},integer}],{15,{c,atom,[session],unknown}}}],{2,{c,atom,[expired],unknown}}},{c,tuple,[{c,atom,[ok],unknown},any],{2,{c,atom,[ok],unknown}}},{c,tuple,[{c,atom,[persistent],unknown},{c,tuple,[{c,atom,[session],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,binary,[0,128],unknown},{c,atom,[false,true],unknown},{c,map,{[],any,any},unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown},{c,atom,[false,true],unknown},{c,opaque,[{opaque,emqx_inflight,inflight,[],{c,tuple,[any,any,any],{3,any}}}],unknown},{c,tuple,[any,any,any,any,any,any,any,any,any,any,any],{11,any}},{c,number,{int_rng,1,1114111},integer},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown},{c,map,{[],any,any},unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown},{c,number,{int_rng,1,pos_inf},integer}],{15,{c,atom,[session],unknown}}}],{2,{c,atom,[persistent],unknown}}}]},{3,[{c,tuple,[{c,atom,[ok],unknown},{c,list,[any,{c,nil,[],unknown}],unknown},any],{3,{c,atom,[ok],unknown}}}]},{4,[{c,tuple,[{c,atom,[living],unknown},{c,atom,any,unknown},{c,identifier,[pid],unknown},{c,union,[none,none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},none,{c,tuple,[{c,atom,[session],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,binary,[0,128],unknown},{c,atom,[false,true],unknown},{c,map,{[],any,any},unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown},{c,atom,[false,true],unknown},{c,opaque,[{opaque,emqx_inflight,inflight,[],{c,tuple,[any,any,any],{3,any}}}],unknown},{c,tuple,[any,any,any,any,any,any,any,any,any,any,any],{11,any}},{c,number,{int_rng,1,1114111},integer},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown},{c,map,{[],any,any},unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown},{c,number,{int_rng,1,pos_inf},integer}],{15,{c,atom,[session],unknown}}},none,none,none],unknown}],{4,{c,atom,[living],unknown}}}]}],unknown},none,none,{c,map,{[],{c,atom,any,unknown},any},unknown}],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},any]},{emqx_bridge_proto_v4,restart_bridges_to_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_resource_proto_v1,create,5} => {any,[{c,binary,[8,0],unknown},{c,binary,[8,0],unknown},{c,atom,any,unknown},any,{c,map,{[{{c,atom,[auto_restart_interval],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[auto_retry_interval],unknown},optional,{c,number,any,integer}},{{c,atom,[batch_size],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[batch_time],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[health_check_interval],unknown},optional,{c,number,any,integer}},{{c,atom,[health_check_timeout],unknown},optional,{c,number,any,integer}},{{c,atom,[inflight_window],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[max_buffer_bytes],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[query_mode],unknown},optional,{c,atom,[async,no_queries,simple_async,simple_sync,sync],unknown}},{{c,atom,[resume_interval],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[start_after_created],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[start_timeout],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[wait_for_resource_ready],unknown},optional,{c,number,any,integer}},{{c,atom,[worker_pool_size],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}}],none,none},unknown}]},{emqx_bridge_proto_v2,restart_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_management_proto_v3,broker_info,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_metrics,all,0} => {{c,list,[{c,tuple,[any,{c,number,any,integer}],{2,any}},{c,nil,[],unknown}],unknown},[]},{emqx_node_rebalance_status_proto_v1,evacuation_status,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_exhook_mgr,all_servers_info,0} => {any,[]},{emqx_alarm,get_alarms,1} => {any,[{c,atom,[activated,all,deactivated],unknown}]},{emqx_plugin_libs_proto_v1,get_metrics,3} => {any,[{c,atom,any,unknown},{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}]},{emqx_exhook_proto_v1,all_servers_info,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{ssl_pem_cache,clear,0} => {any,[]},{emqx_resource,remove_local,1} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},none,none,none],unknown},[{c,binary,[8,0],unknown}]},{emqx_bridge_proto_v4,start_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_bridge,list,0} => {any,[]},{emqx_retainer_proto_v1,wait_dispatch_complete,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown}]},{emqx_node_rebalance,stop,0} => {any,[]},{emqx_mgmt_api_cluster,join,1} => {any,[any]},{emqx_node_rebalance_evacuation_proto_v1,available_nodes,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_prometheus,do_stop,0} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},{c,atom,[not_found,restarting,running,simple_one_for_one],unknown}],{2,{c,atom,[error],unknown}}},none,none,none],unknown},[]},{emqx_node_rebalance_api_proto_v1,node_rebalance_evacuation_start,2} => {any,[{c,atom,any,unknown},{c,map,{[{{c,atom,[conn_evict_rate],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[migrate_to],unknown},optional,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}},{{c,atom,[server_reference],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}},{{c,atom,[sess_evict_rate],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[wait_takeover],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}}],none,none},unknown}]},{emqx_telemetry_proto_v1,get_node_uuid,1} => {any,[{c,atom,any,unknown}]},{emqx_cm_proto_v2,kickout_client,2} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}]},{emqx_management_proto_v3,node_info,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_conf,get_node_and_config,1} => {{c,tuple,[{c,atom,any,unknown},any],{2,any}},[{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],unknown}]},{emqx_gateway_cm_proto_v1,cast,4} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown},any]},{emqx_node_rebalance,connection_count,0} => {{c,tuple,[{c,atom,[ok],unknown},any],{2,{c,atom,[ok],unknown}}},[]},{emqx_node_rebalance_status,local_status,0} => {{c,union,[{c,atom,[disabled],unknown},none,none,none,none,none,{c,tuple_set,[{2,[{c,tuple,[{c,atom,[evacuation],unknown},{c,map,{[{{c,atom,[connection_eviction_rate],unknown},mandatory,any},{{c,atom,[connection_goal],unknown},mandatory,{c,number,{int_set,[0]},integer}},{{c,atom,[session_eviction_rate],unknown},mandatory,any},{{c,atom,[session_goal],unknown},mandatory,{c,number,{int_set,[0]},integer}},{{c,atom,[session_recipients],unknown},mandatory,any},{{c,atom,[state],unknown},mandatory,any},{{c,atom,[stats],unknown},mandatory,{c,map,{[{{c,atom,[current_connected],unknown},mandatory,any},{{c,atom,[current_sessions],unknown},mandatory,any},{{c,atom,[initial_connected],unknown},mandatory,any},{{c,atom,[initial_sessions],unknown},mandatory,any}],none,none},unknown}}],none,none},unknown}],{2,{c,atom,[evacuation],unknown}}},{c,tuple,[{c,atom,[rebalance],unknown},{c,map,{[],{c,atom,[connection_eviction_rate,connection_goal,coordinator_node,disconnected_session_goal,recipients,session_eviction_rate,state,stats],unknown},any},unknown}],{2,{c,atom,[rebalance],unknown}}}]}],unknown},none,none,none],unknown},[]},{emqx,is_running,0} => {{c,atom,[false,true],unknown},[]},{emqx_conf_proto_v1,reset,2} => {any,[{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_resource,create_dry_run_local,2} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},none,none,none],unknown},[{c,atom,any,unknown},any]},{emqx_management_proto_v3,call_client,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},any]},{emqx_cm_proto_v2,takeover_session,2} => {any,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_conf_app,sync_data_from_node,0} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,binary,[8,0],unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},[]},{emqx_conf_proto_v1,get_config,3} => {any,[{c,atom,any,unknown},{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],unknown},any]},{emqx_proto_v1,is_running,1} => {any,[{c,atom,any,unknown}]},{emqx_exhook_mgr,server_info,1} => {any,[any]},{emqx_cm_proto_v2,get_chann_conn_mod,2} => {any,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_conf_proto_v2,get_override_config_file,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_management_proto_v1,broker_info,1} => {any,[{c,atom,any,unknown}]},{emqx_bridge_proto_v1,list_bridges,1} => {any,[{c,atom,any,unknown}]},{emqx_mgmt_api_plugins,describe_package,1} => {{c,tuple,[{c,atom,any,unknown},{c,list,[{c,map,{[],any,any},unknown},{c,nil,[],unknown}],unknown}],{2,any}},[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_mgmt_api_plugins_proto_v1,ensure_action,2} => {any,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,atom,[restart,start,stop],unknown}]},{emqx_gateway_cm,do_call,4} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown},any]},{emqx_slow_subs_proto_v1,clear_history,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_bridge_proto_v3,list_bridges_on_nodes,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_gateway_cm_proto_v1,get_chan_info,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_cm_proto_v2,get_chan_stats,2} => {any,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_rule_engine_proto_v1,reset_metrics,1} => {any,[{c,binary,[8,0],unknown}]},{emqx_resource_proto_v1,reset_metrics,1} => {any,[{c,binary,[8,0],unknown}]},{emqx_gateway_cm,do_takeover_session,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx,remove_config,2} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,map,{[{{c,atom,[config],unknown},optional,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},none,none,none,none,{c,map,{[],{c,atom,any,unknown},any},unknown}],unknown}},{{c,atom,[post_config_update],unknown},optional,{c,map,{[],{c,atom,any,unknown},any},unknown}},{{c,atom,[raw_config],unknown},optional,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},none,none,none,none,{c,map,{[],{c,binary,[8,0],unknown},any},unknown}],unknown}}],none,none},unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_management_proto_v3,unsubscribe,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,binary,[8,0],unknown}]},{emqx_cm_proto_v1,get_chann_conn_mod,2} => {any,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_metrics_worker,get_metrics,2} => {{c,map,{[{{c,atom,[counters],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[gauges],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[rate],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[slides],unknown},mandatory,{c,map,{[],any,any},unknown}}],none,none},unknown},[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}]},{emqx_mgmt_api_plugins,install_package,2} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},none,none,none],unknown},[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[none,none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},{c,number,{int_rng,0,1114111},integer},none,none,none,none],unknown},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},{c,number,{int_rng,0,255},integer},none,none,none,none],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_gateway_api_listeners_proto_v1,listeners_cluster_status,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,list,[any,{c,nil,[],unknown}],unknown}]},{emqx_topic_metrics_proto_v1,reset,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_management_proto_v3,unsubscribe_batch,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,list,[{c,binary,[8,0],unknown},{c,nil,[],unknown}],unknown}]},{emqx_mgmt_api_configs,get_full_config,0} => {{c,map,{[],any,any},unknown},[]},{emqx_management_proto_v2,list_listeners,1} => {any,[{c,atom,any,unknown}]},{emqx_gateway_cm,do_get_chan_stats,3} => {any,[any,any,any]},{emqx_node_rebalance_evacuation,is_node_available,0} => {{c,atom,any,unknown},[]},{emqx_ft_storage_exporter_fs_proto_v1,read_export_file,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},none,none,none,{c,list,[{c,union,[{c,atom,any,unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},{c,number,{int_rng,0,1114111},integer},none,none,none,none],unknown},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_mgmt_trace_proto_v1,read_trace_file,4} => {any,[{c,atom,any,unknown},{c,binary,[8,0],unknown},{c,number,{int_rng,0,pos_inf},integer},{c,number,{int_rng,0,pos_inf},integer}]},{emqx_exhook_proto_v1,server_hooks_metrics,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},any]},{emqx_proto_v2,get_metrics,1} => {any,[{c,atom,any,unknown}]},{emqx_conf_proto_v2,update,3} => {any,[{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},any,{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_topic_metrics,metrics,0} => {{c,list,[{c,map,{[{{c,atom,[create_time],unknown},mandatory,any},{{c,atom,[metrics],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[reset_time],unknown},optional,any},{{c,atom,[topic],unknown},mandatory,any}],none,none},unknown},{c,nil,[],unknown}],unknown},[]},{emqx_bridge_proto_v3,start_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_delayed,get_delayed_message,1} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,atom,[not_found],unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,map,{[{{c,atom,[delayed_interval],unknown},mandatory,any},{{c,atom,[delayed_remaining],unknown},mandatory,{c,number,any,integer}},{{c,atom,[expected_at],unknown},mandatory,{c,binary,[8,0],unknown}},{{c,atom,[from_clientid],unknown},mandatory,{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}},{{c,atom,[from_username],unknown},mandatory,any},{{c,atom,[msgid],unknown},mandatory,{c,binary,[8,0],unknown}},{{c,atom,[node],unknown},mandatory,any},{{c,atom,[payload],unknown},optional,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},{c,number,{int_rng,0,255},integer},none,none,none,none],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},none,none,none,none,none],unknown}},{{c,atom,[publish_at],unknown},mandatory,{c,binary,[8,0],unknown}},{{c,atom,[qos],unknown},mandatory,any},{{c,atom,[topic],unknown},mandatory,{c,binary,[8,0],unknown}}],none,none},unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},[any]},{emqx_proto_v1,clean_authz_cache,1} => {any,[{c,atom,any,unknown}]},{emqx_proto_v2,clean_authz_cache,1} => {any,[{c,atom,any,unknown}]},{emqx_mgmt,do_unsubscribe_batch,2} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,atom,[channel_not_found],unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[unsubscribe],unknown},{c,list,[{c,tuple,[any,any],{2,any}},{c,nil,[],unknown}],unknown}],{2,{c,atom,[unsubscribe],unknown}}}]}],unknown},[any,any]},{emqx_mgmt_api_plugins_proto_v1,describe_package,1} => {any,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_conf_proto_v1,remove_config,3} => {any,[{c,atom,any,unknown},{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_cm_proto_v2,kick_session,3} => {any,[{c,atom,[discard,kick],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_mgmt_trace_proto_v2,read_trace_file,4} => {any,[{c,atom,any,unknown},{c,binary,[8,0],unknown},{c,number,{int_rng,0,pos_inf},integer},{c,number,{int_rng,0,pos_inf},integer}]},{emqx_gateway_cm,do_lookup_by_clientid,2} => {{c,list,[any,{c,nil,[],unknown}],unknown},[{c,union,[{c,atom,any,unknown},none,none,none,{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown},{c,number,any,unknown},none,none,none,none],unknown},any]},{emqx_management_proto_v2,list_subscriptions,1} => {any,[{c,atom,any,unknown}]},{emqx_management_proto_v3,get_full_config,1} => {any,[{c,atom,any,unknown}]},{emqx_management_proto_v1,call_client,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},any]},{emqx,update_config,3} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,map,{[{{c,atom,[config],unknown},optional,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},none,none,none,none,{c,map,{[],{c,atom,any,unknown},any},unknown}],unknown}},{{c,atom,[post_config_update],unknown},optional,{c,map,{[],{c,atom,any,unknown},any},unknown}},{{c,atom,[raw_config],unknown},optional,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},none,none,none,none,{c,map,{[],{c,binary,[8,0],unknown},any},unknown}],unknown}}],none,none},unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},any,{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_mgmt_trace_proto_v2,trace_file,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[{c,atom,any,unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},{c,number,{int_rng,0,1114111},integer},none,none,none,none],unknown},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_gateway_http,gateway_status,1} => {{c,map,{[{{c,atom,[current_connections],unknown},optional,any},{{c,atom,[max_connections],unknown},optional,{c,number,{int_set,[0]},integer}},{{c,atom,[node],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[status],unknown},mandatory,{c,atom,[running,stopped,unloaded],unknown}}],none,none},unknown},[{c,atom,any,unknown}]},{emqx_ft_storage_fs_proto_v1,list_assemblers,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,tuple,[{c,binary,[8,0],unknown},{c,binary,[8,0],unknown}],{2,any}}]},{emqx_dashboard_monitor,current_rate,1} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[badrpc],unknown},any],{2,{c,atom,[badrpc],unknown}}},{c,tuple,[{c,atom,[ok],unknown},any],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,atom,any,unknown}]},{emqx_mgmt_api_listeners,do_list_listeners,0} => {{c,map,{[],{c,binary,"( ",unknown},{c,union,[{c,atom,any,unknown},none,none,none,{c,list,[{c,map,{[],any,any},unknown},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}},unknown},[]},{emqx_resource,create_local,5} => {{c,tuple,[{c,atom,[ok],unknown},{c,map,{[{{c,atom,[callback_mode],unknown},mandatory,{c,atom,[always_sync,async_if_possible],unknown}},{{c,atom,[config],unknown},mandatory,any},{{c,atom,[error],unknown},mandatory,any},{{c,atom,[id],unknown},mandatory,{c,binary,[8,0],unknown}},{{c,atom,[mod],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[query_mode],unknown},mandatory,{c,atom,[async,no_queries,simple_async,simple_sync,sync],unknown}},{{c,atom,[state],unknown},mandatory,any},{{c,atom,[status],unknown},mandatory,{c,atom,[connected,connecting,disconnected,stopped],unknown}}],none,none},unknown}],{2,{c,atom,[ok],unknown}}},[{c,binary,[8,0],unknown},{c,binary,[8,0],unknown},{c,atom,any,unknown},any,{c,map,{[{{c,atom,[auto_restart_interval],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[auto_retry_interval],unknown},optional,{c,number,any,integer}},{{c,atom,[batch_size],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[batch_time],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[health_check_interval],unknown},optional,{c,number,any,integer}},{{c,atom,[health_check_timeout],unknown},optional,{c,number,any,integer}},{{c,atom,[inflight_window],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[max_buffer_bytes],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[query_mode],unknown},optional,{c,atom,[async,no_queries,simple_async,simple_sync,sync],unknown}},{{c,atom,[resume_interval],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[start_after_created],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[start_timeout],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[wait_for_resource_ready],unknown},optional,{c,number,any,integer}},{{c,atom,[worker_pool_size],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}}],none,none},unknown}]},{emqx_management_proto_v2,node_info,1} => {any,[{c,atom,any,unknown}]},{emqx_gateway_cm_proto_v1,get_chann_conn_mod,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_management_proto_v2,broker_info,1} => {any,[{c,atom,any,unknown}]},{emqx_broker,dispatch,2} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,atom,[no_subscribers,not_running],unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,number,{int_rng,0,pos_inf},integer}],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,binary,[8,0],unknown},{c,tuple,[{c,atom,[delivery],unknown},{c,identifier,[pid],unknown},{c,tuple,[{c,atom,[message],unknown},{c,binary,[8,0],unknown},any,{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,map,{[],{c,atom,any,unknown},{c,atom,[false,true],unknown}},unknown},{c,map,{[{{c,atom,[allow_publish],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[peerhost],unknown},optional,{c,tuple_set,[{4,[{c,tuple,[any,any,any,any],{4,any}}]},{8,[{c,tuple,[any,any,any,any,any,any,any,any],{8,any}}]}],unknown}},{{c,atom,[properties],unknown},optional,{c,map,{[],any,any},unknown}},{{c,atom,[proto_ver],unknown},optional,{c,union,[none,{c,binary,[8,0],unknown},none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown}},{{c,atom,[protocol],unknown},optional,{c,atom,any,unknown}},{{c,atom,[username],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}}],{c,atom,any,unknown},any},unknown},{c,binary,[8,0],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},{c,number,{int_rng,0,255},integer},none,none,none,none],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},none,none,none,none,none],unknown},{c,number,any,integer},any],{10,{c,atom,[message],unknown}}}],{3,{c,atom,[delivery],unknown}}}]},{emqx_conf_proto_v1,get_override_config_file,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_session_router,resume_begin,2} => {any,[{c,identifier,[pid],unknown},{c,binary,[8,0],unknown}]},{emqx_proto_v2,get_stats,1} => {any,[{c,atom,any,unknown}]},{emqx_slow_subs_proto_v1,get_history,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_mgmt_trace_proto_v2,get_trace_size,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_ft_storage_fs_proxy,lookup_local_assembler,1} => {any,[any]},{emqx_telemetry,get_node_uuid,0} => {any,[]},{emqx_license_proto_v2,remote_connection_counts,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_proto_v1,get_metrics,1} => {any,[{c,atom,any,unknown}]},{emqx_cm_proto_v2,lookup_client,2} => {any,[{c,atom,any,unknown},{c,tuple_set,[{2,[{c,tuple,[{c,atom,[clientid],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}],{2,{c,atom,[clientid],unknown}}},{c,tuple,[{c,atom,[username],unknown},{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}],{2,{c,atom,[username],unknown}}}]}],unknown}]},{emqx_delayed_proto_v1,delete_delayed_message,2} => {any,[{c,atom,any,unknown},{c,binary,[8,0],unknown}]},{emqx_node_rebalance_agent,disable,1} => {any,[any]},{emqx_bridge_resource,start,2} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},none,none,none],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},{c,number,{int_rng,0,255},integer},none,none,none,none],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},{c,number,{int_rng,0,255},integer},none,none,none,none],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_conf_proto_v2,reset,3} => {any,[{c,atom,any,unknown},{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_ft_storage_fs_reader,read,2} => {any,[{c,identifier,[pid],unknown},{c,number,{int_rng,1,pos_inf},integer}]},{emqx_cm_proto_v2,takeover_finish,2} => {any,[{c,atom,any,unknown},{c,identifier,[pid],unknown}]},{emqx_trace,trace_file,1} => {{c,tuple_set,[{3,[{c,tuple,[{c,atom,[error],unknown},{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown},{c,atom,any,unknown}],{3,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown},{c,binary,[8,0],unknown}],{3,{c,atom,[ok],unknown}}}]}],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[{c,atom,any,unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},{c,number,{int_rng,0,1114111},integer},none,none,none,none],unknown},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_management_proto_v1,list_subscriptions,1} => {any,[{c,atom,any,unknown}]},{emqx_node_rebalance_proto_v1,session_counts,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_bridge_proto_v1,lookup_from_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_conf_proto_v2,get_config,2} => {any,[{c,atom,any,unknown},{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],unknown}]},{emqx_proto_v1,get_stats,1} => {any,[{c,atom,any,unknown}]},{emqx_ft_storage_fs_proto_v1,pread,5} => {any,[{c,atom,any,unknown},{c,tuple,[{c,binary,[8,0],unknown},{c,binary,[8,0],unknown}],{2,any}},{c,map,{[{{c,atom,[fragment],unknown},mandatory,{c,tuple_set,[{2,[{c,tuple,[{c,atom,[filemeta],unknown},{c,map,{[{{c,atom,[checksum],unknown},optional,{c,tuple,[{c,atom,any,unknown},{c,binary,[8,0],unknown}],{2,any}}},{{c,atom,[expire_at],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[name],unknown},mandatory,{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown}},{{c,atom,[segments_ttl],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[size],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[user_data],unknown},optional,{c,union,[{c,atom,[false,null,true],unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[{c,atom,[false,null,true],unknown},{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,nil,[],unknown}],unknown},{c,number,any,unknown},none,none,none,{c,map,{[],{c,binary,[8,0],unknown},any},unknown}],unknown},{c,nil,[],unknown}],unknown},{c,number,any,unknown},none,none,none,{c,map,{[],{c,binary,[8,0],unknown},{c,union,[{c,atom,[false,null,true],unknown},{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,nil,[],unknown}],unknown},{c,number,any,unknown},none,none,none,{c,map,{[],{c,binary,[8,0],unknown},any},unknown}],unknown}},unknown}],unknown}}],none,none},unknown}],{2,{c,atom,[filemeta],unknown}}},{c,tuple,[{c,atom,[segment],unknown},{c,map,{[{{c,atom,[offset],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[size],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}}],none,none},unknown}],{2,{c,atom,[segment],unknown}}}]}],unknown}},{{c,atom,[path],unknown},mandatory,{c,union,[{c,atom,any,unknown},none,none,none,{c,list,[{c,union,[{c,atom,any,unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},{c,number,{int_rng,0,1114111},integer},none,none,none,none],unknown},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}},{{c,atom,[size],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[timestamp],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}}],none,none},unknown},{c,number,{int_rng,0,pos_inf},integer},{c,number,{int_rng,0,pos_inf},integer}]},{emqx_conf_proto_v2,get_all,1} => {any,[{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],unknown}]},{emqx_authz_cache,drain_cache,1} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},{c,atom,[not_found],unknown}],{2,{c,atom,[error],unknown}}},none,none,none],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}]},{emqx_conf_proto_v2,sync_data_from_node,1} => {any,[{c,atom,any,unknown}]},{emqx_node_rebalance_evacuation,start,1} => {any,[{c,map,{[],any,any},unknown}]},{emqx_prometheus_proto_v1,start,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_mgmt,do_unsubscribe,2} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,atom,[channel_not_found],unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[unsubscribe],unknown},{c,list,[{c,tuple,[{c,binary,[8,0],unknown},{c,map,{[],any,any},unknown}],{2,any}},{c,nil,[],unknown}],nonempty}],{2,{c,atom,[unsubscribe],unknown}}}]}],unknown},[any,any]},{emqx_ft_storage_exporter_fs_proto_v1,list_exports,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,map,{[{{c,atom,[following],unknown},optional,{c,var,'_LocalCursor',unknown}},{{c,atom,[limit],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[transfer],unknown},optional,{c,tuple,[{c,binary,[8,0],unknown},{c,binary,[8,0],unknown}],{2,any}}}],none,none},unknown}]},{emqx_cm,do_get_chan_stats,2} => {any,[any,any]},{emqx_ft_storage_exporter_fs_proxy,list_exports_local,1} => {any,[any]},{emqx_node_rebalance,start,1} => {any,[{c,map,{[],any,any},unknown}]},{emqx_bridge_proto_v4,list_bridges_on_nodes,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_license_proto_v1,remote_connection_counts,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_cm_proto_v1,takeover_session,2} => {any,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_bridge_proto_v4,restart_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_slow_subs,clear_history,0} => {any,[]},{emqx_mgmt_api_plugins_proto_v1,get_plugins,0} => {any,[]},{emqx_management_proto_v2,get_full_config,1} => {any,[{c,atom,any,unknown}]},{emqx_proto_v2,is_running,1} => {any,[{c,atom,any,unknown}]},{emqx_gateway_cm_proto_v1,set_chan_stats,4} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown},{c,list,[{c,tuple,[{c,atom,any,unknown},any],{2,any}},{c,nil,[],unknown}],unknown}]},{emqx_bridge_api,lookup_from_local_node,2} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,atom,[not_found],unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},any],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_management_proto_v3,list_listeners,1} => {any,[{c,atom,any,unknown}]},{emqx_management_proto_v2,unsubscribe_batch,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,list,[{c,binary,[8,0],unknown},{c,nil,[],unknown}],unknown}]},{emqx_bridge_proto_v4,stop_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_mgmt_trace_proto_v1,trace_file,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[{c,atom,any,unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},{c,number,{int_rng,0,1114111},integer},none,none,none,none],unknown},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_bridge_resource,restart,2} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},none,none,none],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},{c,number,{int_rng,0,255},integer},none,none,none,none],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},{c,number,{int_rng,0,255},integer},none,none,none,none],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_delayed,delete_delayed_message,1} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},{c,atom,[not_found],unknown}],{2,{c,atom,[error],unknown}}},none,none,none],unknown},[any]},{emqx_mgmt_api_trace,get_trace_size,0} => {{c,map,{[],any,any},unknown},[]},{emqx_shared_sub,do_dispatch_with_ack,4} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},none,none,none],unknown},[{c,identifier,[pid,port],unknown},any,any,{c,tuple,[{c,atom,[message],unknown},{c,binary,[8,0],unknown},any,{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,map,{[],{c,atom,any,unknown},{c,atom,[false,true],unknown}},unknown},{c,map,{[{{c,atom,[allow_publish],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[peerhost],unknown},optional,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown}},{{c,atom,[properties],unknown},optional,{c,map,{[],{c,atom,any,unknown},any},unknown}},{{c,atom,[proto_ver],unknown},optional,{c,union,[none,{c,binary,[8,0],unknown},none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown}},{{c,atom,[protocol],unknown},optional,{c,atom,any,unknown}},{{c,atom,[username],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}}],{c,atom,any,unknown},any},unknown},{c,binary,[8,0],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},{c,number,{int_rng,0,255},integer},none,none,none,none],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},none,none,none,none,none],unknown},{c,number,any,integer},any],{10,{c,atom,[message],unknown}}}]},{emqx,reset_config,2} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,map,{[{{c,atom,[config],unknown},optional,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},none,none,none,none,{c,map,{[],{c,atom,any,unknown},any},unknown}],unknown}},{{c,atom,[post_config_update],unknown},optional,{c,map,{[],{c,atom,any,unknown},any},unknown}},{{c,atom,[raw_config],unknown},optional,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},none,none,none,none,{c,map,{[],{c,binary,[8,0],unknown},any},unknown}],unknown}}],none,none},unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},any]},{emqx_authn_api,lookup_from_local_node,2} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,tuple,[{c,atom,any,unknown},{c,union,[{c,atom,[not_found_resource],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}],{2,any}}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,tuple,[{c,atom,any,unknown},{c,atom,[connected,connecting,disconnected,stopped],unknown},{c,map,{[{{c,atom,[counters],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[gauges],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[rate],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[slides],unknown},mandatory,{c,map,{[],any,any},unknown}}],none,none},unknown},{c,map,{[{{c,atom,[counters],unknown},optional,{c,map,{[],any,any},unknown}},{{c,atom,[gauges],unknown},optional,{c,map,{[],any,any},unknown}},{{c,atom,[rate],unknown},optional,{c,map,{[],any,any},unknown}},{{c,atom,[slides],unknown},optional,{c,map,{[],any,any},unknown}}],none,none},unknown}],{4,any}}],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,atom,any,unknown},{c,binary,[8,0],unknown}]},{emqx_management_proto_v1,unsubscribe,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,binary,[8,0],unknown}]},{emqx_management_proto_v2,call_client,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},any]},{emqx_persistent_session_proto_v1,resume_end,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,identifier,[pid],unknown},{c,binary,[8,0],unknown}]},{emqx_conf_proto_v2,remove_config,3} => {any,[{c,atom,any,unknown},{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_proto_v2,deactivate_alarm,2} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}]},{emqx_node_rebalance,session_count,0} => {{c,tuple,[{c,atom,[ok],unknown},any],{2,{c,atom,[ok],unknown}}},[]},{emqx_topic_metrics_proto_v1,metrics,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_mgmt_api_plugins_proto_v1,delete_package,1} => {any,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_persistent_session_proto_v1,resume_begin,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,identifier,[pid],unknown},{c,binary,[8,0],unknown}]},{emqx_proto_v1,clean_authz_cache,2} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}]},{emqx_bridge_api,get_metrics_from_local_node,2} => {{c,map,{[{{c,atom,[dropped],unknown},mandatory,{c,number,any,integer}},{{c,atom,['dropped.expired'],unknown},mandatory,{c,number,any,integer}},{{c,atom,['dropped.other'],unknown},mandatory,{c,number,any,integer}},{{c,atom,['dropped.queue_full'],unknown},mandatory,{c,number,any,integer}},{{c,atom,['dropped.resource_not_found'],unknown},mandatory,{c,number,any,integer}},{{c,atom,['dropped.resource_stopped'],unknown},mandatory,{c,number,any,integer}},{{c,atom,[failed],unknown},mandatory,{c,number,any,integer}},{{c,atom,[inflight],unknown},mandatory,any},{{c,atom,[late_reply],unknown},mandatory,{c,number,any,integer}},{{c,atom,[matched],unknown},mandatory,{c,number,any,integer}},{{c,atom,[queuing],unknown},mandatory,any},{{c,atom,[rate],unknown},mandatory,any},{{c,atom,[rate_last5m],unknown},mandatory,any},{{c,atom,[rate_max],unknown},mandatory,any},{{c,atom,[received],unknown},mandatory,{c,number,any,integer}},{{c,atom,[retried],unknown},mandatory,{c,number,any,integer}},{{c,atom,[success],unknown},mandatory,{c,number,any,integer}}],none,none},unknown},[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},{c,number,{int_rng,0,255},integer},none,none,none,none],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},{c,number,{int_rng,0,255},integer},none,none,none,none],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_delayed_proto_v1,get_delayed_message,2} => {any,[{c,atom,any,unknown},{c,binary,[8,0],unknown}]},{emqx_shared_sub_proto_v1,send,4} => {any,[{c,atom,any,unknown},{c,identifier,[pid],unknown},{c,binary,[8,0],unknown},any]},{emqx_eviction_agent,evict_sessions,3} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},{c,atom,[disabled],unknown}],{2,{c,atom,[error],unknown}}},none,none,none],unknown},[any,{c,union,[{c,atom,any,unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},any]},{emqx_management_proto_v1,node_info,1} => {any,[{c,atom,any,unknown}]},{emqx_management_proto_v3,subscribe,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,list,[{c,tuple,[{c,binary,[8,0],unknown},{c,map,{[{{c,atom,[nl],unknown},mandatory,{c,number,{int_set,[0,1]},integer}},{{c,atom,[qos],unknown},mandatory,{c,number,{int_set,[0,1,2]},integer}},{{c,atom,[rap],unknown},mandatory,{c,number,{int_set,[0,1]},integer}},{{c,atom,[rh],unknown},mandatory,{c,number,{int_set,[0,1,2]},integer}},{{c,atom,[share],unknown},optional,{c,binary,[8,0],unknown}}],{c,atom,any,unknown},any},unknown}],{2,any}},{c,nil,[],unknown}],unknown}]},{emqx_topic_metrics_proto_v1,reset,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,binary,[8,0],unknown}]},{emqx_node_rebalance_agent,enable,1} => {any,[any]},{emqx_mgmt_trace_proto_v1,get_trace_size,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_node_rebalance_status,rebalance_status,0} => {{c,tuple,[{c,atom,any,unknown},{c,union,[{c,atom,[disabled],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[enabled],unknown},{c,map,{[],any,any},unknown}],{2,{c,atom,[enabled],unknown}}},none,none,none],unknown}],{2,any}},[]},{emqx_license_resources,local_connection_count,0} => {any,[]},{emqx_cm,lookup_client,1} => {{c,list,[any,{c,nil,[],unknown}],unknown},[{c,tuple_set,[{2,[{c,tuple,[{c,atom,[clientid],unknown},any],{2,{c,atom,[clientid],unknown}}},{c,tuple,[{c,atom,[username],unknown},any],{2,{c,atom,[username],unknown}}}]}],unknown}]},{emqx_management_proto_v2,subscribe,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,list,[{c,tuple,[{c,binary,[8,0],unknown},{c,map,{[{{c,atom,[nl],unknown},mandatory,{c,number,{int_set,[0,1]},integer}},{{c,atom,[qos],unknown},mandatory,{c,number,{int_set,[0,1,2]},integer}},{{c,atom,[rap],unknown},mandatory,{c,number,{int_set,[0,1]},integer}},{{c,atom,[rh],unknown},mandatory,{c,number,{int_set,[0,1,2]},integer}},{{c,atom,[share],unknown},optional,{c,binary,[8,0],unknown}}],{c,atom,any,unknown},any},unknown}],{2,any}},{c,nil,[],unknown}],unknown}]},{emqx_cm,kick_session,1} => {{c,atom,[ok],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}]},{emqx_cm_proto_v1,kick_session,3} => {any,[{c,atom,[discard,kick],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_dashboard_proto_v1,current_rate,1} => {any,[{c,atom,any,unknown}]},{emqx_bridge_proto_v3,start_bridges_to_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_ft_storage_fs_reader_proto_v1,read,3} => {any,[{c,atom,any,unknown},{c,identifier,[pid],unknown},{c,number,{int_rng,1,pos_inf},integer}]},{emqx_plugins_proto_v1,get_tar,3} => {any,[{c,atom,any,unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown}]},{emqx_bridge_proto_v2,start_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_resource,recreate_local,4} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,atom,[not_found,updating_to_incorrect_resource_type],unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,map,{[{{c,atom,[callback_mode],unknown},mandatory,{c,atom,[always_sync,async_if_possible],unknown}},{{c,atom,[config],unknown},mandatory,any},{{c,atom,[error],unknown},mandatory,any},{{c,atom,[id],unknown},mandatory,{c,binary,[8,0],unknown}},{{c,atom,[mod],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[query_mode],unknown},mandatory,{c,atom,[async,no_queries,simple_async,simple_sync,sync],unknown}},{{c,atom,[state],unknown},mandatory,any},{{c,atom,[status],unknown},mandatory,{c,atom,[connected,connecting,disconnected,stopped],unknown}}],none,none},unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,binary,[8,0],unknown},{c,atom,any,unknown},any,{c,map,{[{{c,atom,[auto_restart_interval],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[auto_retry_interval],unknown},optional,{c,number,any,integer}},{{c,atom,[batch_size],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[batch_time],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[health_check_interval],unknown},optional,{c,number,any,integer}},{{c,atom,[health_check_timeout],unknown},optional,{c,number,any,integer}},{{c,atom,[inflight_window],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[max_buffer_bytes],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[query_mode],unknown},optional,{c,atom,[async,no_queries,simple_async,simple_sync,sync],unknown}},{{c,atom,[resume_interval],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[start_after_created],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[start_timeout],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[wait_for_resource_ready],unknown},optional,{c,number,any,integer}},{{c,atom,[worker_pool_size],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}}],none,none},unknown}]},{emqx_topic_metrics_proto_v1,metrics,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,binary,[8,0],unknown}]},{emqx_bridge_resource,stop,2} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},none,none,none],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},{c,number,{int_rng,0,255},integer},none,none,none,none],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},{c,number,{int_rng,0,255},integer},none,none,none,none],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_mgmt,do_call_client,2} => {any,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},any]},{emqx_exhook_proto_v1,server_info,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},any]},{emqx_retainer_mnesia,active_indices,0} => {{c,tuple,[any,any],{2,any}},[]},{emqx_prometheus_proto_v1,stop,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_proto_v1,get_alarms,2} => {any,[{c,atom,any,unknown},{c,atom,[activated,all,deactivated],unknown}]},{emqx_dashboard_proto_v1,do_sample,2} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,1,pos_inf},integer},none,none,none,none],unknown}]},{emqx_telemetry,get_cluster_uuid,0} => {any,[]},{emqx_bridge_proto_v2,list_bridges,1} => {any,[{c,atom,any,unknown}]},{emqx_node_rebalance_proto_v1,evict_connections,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,number,{int_rng,0,pos_inf},integer}]},{emqx_conf_proto_v1,update,4} => {any,[{c,atom,any,unknown},{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},any,{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_node_rebalance_api_proto_v1,node_rebalance_evacuation_stop,1} => {any,[{c,atom,any,unknown}]},{emqx_broker_proto_v1,list_client_subscriptions,2} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}]},{emqx_broker_proto_v1,forward_async,3} => {any,[{c,atom,any,unknown},{c,binary,[8,0],unknown},{c,tuple,[{c,atom,[delivery],unknown},{c,identifier,[pid],unknown},{c,tuple,[{c,atom,[message],unknown},{c,binary,[8,0],unknown},any,{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,map,{[],{c,atom,any,unknown},{c,atom,[false,true],unknown}},unknown},{c,map,{[{{c,atom,[allow_publish],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[peerhost],unknown},optional,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown}},{{c,atom,[properties],unknown},optional,{c,map,{[],{c,atom,any,unknown},any},unknown}},{{c,atom,[proto_ver],unknown},optional,{c,union,[none,{c,binary,[8,0],unknown},none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown}},{{c,atom,[protocol],unknown},optional,{c,atom,any,unknown}},{{c,atom,[username],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}}],{c,atom,any,unknown},any},unknown},{c,binary,[8,0],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},{c,number,{int_rng,0,255},integer},none,none,none,none],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},none,none,none,none,none],unknown},{c,number,any,integer},any],{10,{c,atom,[message],unknown}}}],{3,{c,atom,[delivery],unknown}}}]},{emqx_cm_proto_v1,kickout_client,2} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}]},{emqx_mgmt,do_subscribe,2} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,atom,[channel_not_found],unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[subscribe],unknown},any],{2,{c,atom,[subscribe],unknown}}}]}],unknown},[any,any]},{emqx_conf_app,get_override_config_file,0} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,map,{[{{c,atom,[msg],unknown},mandatory,any},{{c,atom,[node],unknown},mandatory,{c,atom,any,unknown}}],none,none},unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},any],{2,{c,atom,[ok],unknown}}}]}],unknown},[]},{emqx_gateway_cm,do_cast,4} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown},any]},{emqx_management_proto_v1,subscribe,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,list,[{c,tuple,[{c,binary,[8,0],unknown},{c,map,{[{{c,atom,[nl],unknown},mandatory,{c,number,{int_set,[0,1]},integer}},{{c,atom,[qos],unknown},mandatory,{c,number,{int_set,[0,1,2]},integer}},{{c,atom,[rap],unknown},mandatory,{c,number,{int_set,[0,1]},integer}},{{c,atom,[rh],unknown},mandatory,{c,number,{int_set,[0,1,2]},integer}},{{c,atom,[share],unknown},optional,{c,binary,[8,0],unknown}}],{c,atom,any,unknown},any},unknown}],{2,any}},{c,nil,[],unknown}],unknown}]},{emqx_mgmt_api_plugins,delete_package,1} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},none,none,none],unknown},[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_mgmt_api_plugins_proto_v1,install_package,2} => {any,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,binary,[8,0],unknown}]},{emqx_resource_proto_v1,recreate,4} => {any,[{c,binary,[8,0],unknown},{c,atom,any,unknown},any,{c,map,{[{{c,atom,[auto_restart_interval],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[auto_retry_interval],unknown},optional,{c,number,any,integer}},{{c,atom,[batch_size],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[batch_time],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[health_check_interval],unknown},optional,{c,number,any,integer}},{{c,atom,[health_check_timeout],unknown},optional,{c,number,any,integer}},{{c,atom,[inflight_window],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[max_buffer_bytes],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[query_mode],unknown},optional,{c,atom,[async,no_queries,simple_async,simple_sync,sync],unknown}},{{c,atom,[resume_interval],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[start_after_created],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[start_timeout],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[wait_for_resource_ready],unknown},optional,{c,number,any,integer}},{{c,atom,[worker_pool_size],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}}],none,none},unknown}]},{emqx_authz_cache,drain_cache,0} => {{c,atom,[ok],unknown},[]},{emqx_mgmt_api_plugins,ensure_action,2} => {{c,atom,[ok],unknown},[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,atom,[restart,start,stop],unknown}]},{emqx_broker_proto_v1,list_subscriptions_via_topic,2} => {any,[{c,atom,any,unknown},{c,binary,[8,0],unknown}]},{emqx_trace,trace_file_detail,1} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,map,{[{{c,atom,[file],unknown},mandatory,{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[{c,atom,any,unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},{c,number,{int_rng,0,1114111},integer},none,none,none,none],unknown},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}},{{c,atom,[node],unknown},mandatory,{c,binary,[8,0],unknown}},{{c,atom,[reason],unknown},mandatory,{c,atom,any,unknown}}],none,none},unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,map,{[{{c,atom,[mtime],unknown},mandatory,{c,union,[{c,atom,[undefined],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},{c,tuple,[{c,tuple,[any,any,any],{3,any}},{c,tuple,[any,any,any],{3,any}}],{2,any}},none,none,none],unknown}},{{c,atom,[node],unknown},mandatory,{c,binary,[8,0],unknown}},{{c,atom,[size],unknown},mandatory,{c,union,[{c,atom,[undefined],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown}}],none,none},unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[{c,atom,any,unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},{c,number,{int_rng,0,1114111},integer},none,none,none,none],unknown},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_proto_v1,delete_all_deactivated_alarms,1} => {any,[{c,atom,any,unknown}]},{emqx_prometheus,do_start,0} => {{c,atom,[ok],unknown},[]},{emqx_gateway_cm,do_kick_session,4} => {{c,atom,[ok],unknown},[{c,atom,any,unknown},any,{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_ft_storage_fs_proto_v1,multilist,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,tuple,[{c,binary,[8,0],unknown},{c,binary,[8,0],unknown}],{2,any}},{c,atom,[fragment,result],unknown}]},{emqx_telemetry_proto_v1,get_cluster_uuid,1} => {any,[{c,atom,any,unknown}]},{emqx_node_rebalance,is_node_available,0} => {{c,atom,any,unknown},[]},{emqx_retainer_proto_v2,active_mnesia_indices,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_bridge_proto_v4,lookup_from_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_bridge_proto_v3,list_bridges,1} => {any,[{c,atom,any,unknown}]},{emqx_gateway_cm,do_get_chan_info,3} => {{c,union,[{c,atom,[undefined],unknown},none,none,none,none,none,none,none,none,{c,map,{[{{c,atom,[node],unknown},mandatory,{c,atom,any,unknown}}],any,any},unknown}],unknown},[any,any,any]},{emqx_node_rebalance_status_proto_v1,rebalance_status,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_node_rebalance_proto_v1,disable_rebalance_agent,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,identifier,[pid],unknown}]},{emqx_rule_engine,reset_metrics_for_rule,1} => {{c,atom,[ok],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}]},{emqx_authz_proto_v1,lookup_from_all_nodes,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,atom,any,unknown}]},{emqx_proto_v1,clean_pem_cache,1} => {any,[{c,atom,any,unknown}]},{emqx_conf_proto_v1,get_config,2} => {any,[{c,atom,any,unknown},{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],unknown}]},{emqx_management_proto_v1,get_full_config,1} => {any,[{c,atom,any,unknown}]},{emqx_topic_metrics,reset,1} => {any,[any]},{emqx_node_rebalance_proto_v1,available_nodes,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_proto_v2,clean_pem_cache,1} => {any,[{c,atom,any,unknown}]},{emqx_bridge_proto_v4,stop_bridges_to_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_conf_proto_v1,reset,3} => {any,[{c,atom,any,unknown},{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_broker,subscriptions,1} => {{c,list,[{c,tuple,[any,any],{2,any}},{c,nil,[],unknown}],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,{c,identifier,[pid],unknown},none,none,none,none,none,none],unknown}]},{emqx_mgmt,do_list_subscriptions,0} => {none,[]},{emqx_eviction_agent_proto_v1,evict_session_channel,4} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,map,{[{{c,atom,[clean_start],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[clientid],unknown},optional,{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}},{{c,atom,[conn_mod],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[conn_props],unknown},optional,{c,map,{[],{c,atom,any,unknown},any},unknown}},{{c,atom,[connected],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[connected_at],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[disconnected_at],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[expiry_interval],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[keepalive],unknown},optional,{c,number,{int_rng,0,1114111},integer}},{{c,atom,[peercert],unknown},mandatory,{c,union,[{c,atom,[nossl,undefined],unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[{c,atom,any,unknown},none,none,none,none,none,{c,tuple,any,{any,any}},none,none,none],unknown},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}},{{c,atom,[peername],unknown},mandatory,{c,tuple,[{c,union,[{c,atom,[local,undefined,unspec],unknown},none,none,none,none,none,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown},none,none,none],unknown},any],{2,any}}},{{c,atom,[proto_name],unknown},optional,{c,binary,[8,0],unknown}},{{c,atom,[proto_ver],unknown},optional,{c,union,[none,{c,binary,[8,0],unknown},none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown}},{{c,atom,[receive_maximum],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[sockname],unknown},mandatory,{c,tuple,[{c,union,[{c,atom,[local,undefined,unspec],unknown},none,none,none,none,none,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown},none,none,none],unknown},any],{2,any}}},{{c,atom,[socktype],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[username],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}}],{c,atom,any,unknown},any},unknown},{c,map,{[{{c,atom,[anonymous],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[auth_result],unknown},optional,{c,atom,[bad_authentication_method,bad_clientid_or_password,bad_username_or_password,banned,client_identifier_not_valid,not_authorized,server_busy,server_unavailable,success],unknown}},{{c,atom,[clientid],unknown},mandatory,{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}},{{c,atom,[cn],unknown},optional,{c,binary,[8,0],unknown}},{{c,atom,[dn],unknown},optional,{c,binary,[8,0],unknown}},{{c,atom,[is_bridge],unknown},mandatory,{c,atom,[false,true],unknown}},{{c,atom,[is_superuser],unknown},mandatory,{c,atom,[false,true],unknown}},{{c,atom,[mountpoint],unknown},mandatory,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}},{{c,atom,[password],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}},{{c,atom,[peerhost],unknown},mandatory,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown}},{{c,atom,[protocol],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[sockport],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[username],unknown},mandatory,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}},{{c,atom,[ws_cookie],unknown},optional,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}},{{c,atom,[zone],unknown},mandatory,{c,atom,any,unknown}}],{c,atom,any,unknown},any},unknown}]},{emqx_gateway_cm,do_set_chan_stats,4} => {{c,atom,[false,true],unknown},[any,any,any,any]},{emqx_retainer_dispatcher,wait_dispatch_complete,1} => {{c,atom,[ok],unknown},[any]},{emqx_conf_proto_v2,update,4} => {any,[{c,atom,any,unknown},{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},any,{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_bridge_proto_v3,stop_bridges_to_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_gateway_cm_proto_v1,get_chan_stats,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_ft_storage_exporter_fs_proxy,read_export_file_local,2} => {any,[any,any]},{emqx_conf_proto_v2,remove_config,2} => {any,[{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_stats,getstats,0} => {{c,list,[{c,tuple,any,{any,any}},{c,nil,[],unknown}],unknown},[]},{emqx_mgmt,node_info,0} => {{c,map,{[{{c,atom,[connections],unknown},mandatory,any},{{c,atom,[edition],unknown},mandatory,{c,binary,[0,80],unknown}},{{c,atom,[load1],unknown},optional,{c,number,any,float}},{{c,atom,[load15],unknown},optional,{c,number,any,float}},{{c,atom,[load5],unknown},optional,{c,number,any,float}},{{c,atom,[log_path],unknown},mandatory,{c,binary,[8,0],unknown}},{{c,atom,[max_fds],unknown},mandatory,any},{{c,atom,[memory_total],unknown},mandatory,{c,number,any,unknown}},{{c,atom,[memory_used],unknown},mandatory,{c,number,any,integer}},{{c,atom,[node],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[node_status],unknown},mandatory,{c,atom,[running],unknown}},{{c,atom,[otp_release],unknown},mandatory,{c,binary,[8,0],unknown}},{{c,atom,[process_available],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[process_used],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[role],unknown},mandatory,{c,atom,[core,replicant],unknown}},{{c,atom,[sys_path],unknown},mandatory,{c,binary,[8,0],unknown}},{{c,atom,[uptime],unknown},mandatory,any},{{c,atom,[version],unknown},mandatory,{c,binary,[8,0],unknown}}],none,none},unknown},[]},{emqx_gateway_cm_proto_v1,kick_session,4} => {any,[{c,atom,any,unknown},{c,atom,[discard,kick],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_node_rebalance_api_proto_v1,node_rebalance_stop,1} => {any,[{c,atom,any,unknown}]},{emqx_cm_proto_v2,get_chan_info,2} => {any,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_authn_proto_v1,lookup_from_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,atom,any,unknown},{c,binary,[8,0],unknown}]},{emqx_cm,takeover_finish,2} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,atom,[noproc,timeout,unexpected_exception],unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,union,[none,none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},none,{c,tuple,[{c,atom,[session],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,binary,[0,128],unknown},{c,atom,[false,true],unknown},{c,map,{[],any,any},unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown},{c,atom,[false,true],unknown},{c,opaque,[{opaque,emqx_inflight,inflight,[],{c,tuple,[{c,atom,[inflight],unknown},{c,number,{int_rng,1,pos_inf},integer},{c,opaque,[{opaque,gb_trees,tree,[any,any],{c,tuple,[any,any],{2,any}}}],unknown}],{3,{c,atom,[inflight],unknown}}}}],unknown},{c,tuple,[{c,atom,[mqueue],unknown},{c,atom,[false,true],unknown},{c,number,{int_rng,0,pos_inf},integer},{c,number,{int_rng,0,pos_inf},integer},{c,number,{int_rng,0,pos_inf},integer},{c,union,[{c,atom,[disabled],unknown},none,none,none,none,none,none,none,none,{c,map,{[],any,any},unknown}],unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,any,integer},none,none,none,none],unknown},{c,tuple_set,[{2,[{c,tuple,[any,any],{2,any}}]},{4,[{c,tuple,[any,any,any,any],{4,any}}]}],unknown},{c,tuple,[any,any,any],{3,any}},{c,union,[{c,atom,[undefined],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown},{c,union,[{c,atom,[undefined],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown}],{11,{c,atom,[mqueue],unknown}}},{c,number,{int_rng,1,1114111},integer},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown},{c,map,{[],any,any},unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown},{c,number,{int_rng,1,pos_inf},integer}],{15,{c,atom,[session],unknown}}},none,none,none],unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},none,none,none],unknown},[{c,atom,any,unknown},{c,identifier,[pid],unknown}]},{emqx_gateway_cm_proto_v1,call,5} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown},any,{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown}]},{emqx_mgmt,broker_info,0} => {{c,map,{[{{c,atom,[node],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[node_status],unknown},mandatory,{c,atom,[running],unknown}},{{c,atom,[otp_release],unknown},mandatory,{c,binary,[8,0],unknown}}],any,any},unknown},[]},{emqx_resource,reset_metrics_local,1} => {{c,atom,[ok],unknown},[{c,binary,[8,0],unknown}]},{emqx_cm,do_kick_session,3} => {{c,atom,[ok],unknown},[any,{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_gateway_cm,do_get_chann_conn_mod,3} => {any,[any,any,any]},{emqx_conf_proto_v2,get_config,3} => {any,[{c,atom,any,unknown},{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],unknown},any]},{emqx_resource_proto_v1,remove,1} => {any,[{c,binary,[8,0],unknown}]},{emqx_topic_metrics,reset,0} => {any,[]},{emqx_bridge_proto_v3,restart_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_slow_subs_api,get_history,0} => {{c,list,[{c,map,{[{{c,atom,[clientid],unknown},mandatory,any},{{c,atom,[last_update_time],unknown},mandatory,any},{{c,atom,[node],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[timespan],unknown},mandatory,any},{{c,atom,[topic],unknown},mandatory,any}],none,none},unknown},{c,nil,[],unknown}],unknown},[]},{emqx_node_rebalance_proto_v1,evict_sessions,4} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,number,{int_rng,0,pos_inf},integer},{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,atom,[connected,connecting,disconnected,idle,reauthenticating],unknown}]},{emqx,get_config,1} => {any,[{c,list,[any,{c,nil,[],unknown}],unknown}]},{emqx_bridge_proto_v1,stop_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_bridge_proto_v2,start_bridges_to_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_authz_api_sources,lookup_from_local_node,1} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,tuple,[{c,atom,any,unknown},{c,union,[{c,atom,[not_found_resource],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}],{2,any}}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,tuple,[{c,atom,any,unknown},{c,atom,[connected,connecting,disconnected,stopped],unknown},{c,map,{[{{c,atom,[counters],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[gauges],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[rate],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[slides],unknown},mandatory,{c,map,{[],any,any},unknown}}],none,none},unknown},{c,map,{[{{c,atom,[counters],unknown},optional,{c,map,{[],any,any},unknown}},{{c,atom,[gauges],unknown},optional,{c,map,{[],any,any},unknown}},{{c,atom,[rate],unknown},optional,{c,map,{[],any,any},unknown}},{{c,atom,[slides],unknown},optional,{c,map,{[],any,any},unknown}}],none,none},unknown}],{4,any}}],{2,{c,atom,[ok],unknown}}}]}],unknown},[any]},{emqx_gateway_cm_proto_v1,set_chan_info,4} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown},{c,map,{[],{c,atom,any,unknown},any},unknown}]},{emqx_eviction_agent,evict_session_channel,3} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,union,[{c,atom,[undefined],unknown},none,none,{c,identifier,[pid],unknown},none,none,none,none,none,none],unknown}],{2,{c,atom,[ok],unknown}}}]},{3,[{c,tuple,[{c,atom,[ok],unknown},{c,union,[{c,atom,[undefined],unknown},none,none,{c,identifier,[pid],unknown},none,none,none,none,none,none],unknown},any],{3,{c,atom,[ok],unknown}}}]}],unknown},[any,{c,map,{[{{c,atom,[clean_start],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[clientid],unknown},optional,{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}},{{c,atom,[conn_mod],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[conn_props],unknown},optional,{c,map,{[],{c,atom,any,unknown},any},unknown}},{{c,atom,[connected],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[connected_at],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[disconnected_at],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[expiry_interval],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[keepalive],unknown},optional,{c,number,{int_rng,0,1114111},integer}},{{c,atom,[peercert],unknown},optional,{c,union,[{c,atom,[nossl,undefined],unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[{c,atom,any,unknown},none,none,none,none,none,{c,tuple,any,{any,any}},none,none,none],unknown},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}},{{c,atom,[peername],unknown},mandatory,{c,tuple,[{c,union,[{c,atom,[local,undefined,unspec],unknown},none,none,none,none,none,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown},none,none,none],unknown},any],{2,any}}},{{c,atom,[proto_name],unknown},optional,{c,binary,[8,0],unknown}},{{c,atom,[proto_ver],unknown},optional,{c,union,[none,{c,binary,[8,0],unknown},none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown}},{{c,atom,[receive_maximum],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[sockname],unknown},mandatory,{c,tuple,[{c,union,[{c,atom,[local,undefined,unspec],unknown},none,none,none,none,none,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown},none,none,none],unknown},any],{2,any}}},{{c,atom,[socktype],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[username],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}}],{c,atom,any,unknown},any},unknown},{c,map,{[{{c,atom,[anonymous],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[auth_result],unknown},optional,{c,atom,[bad_authentication_method,bad_clientid_or_password,bad_username_or_password,banned,client_identifier_not_valid,not_authorized,server_busy,server_unavailable,success],unknown}},{{c,atom,[clientid],unknown},mandatory,{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}},{{c,atom,[cn],unknown},optional,{c,binary,[8,0],unknown}},{{c,atom,[dn],unknown},optional,{c,binary,[8,0],unknown}},{{c,atom,[is_bridge],unknown},mandatory,{c,atom,[false,true],unknown}},{{c,atom,[is_superuser],unknown},mandatory,{c,atom,[false,true],unknown}},{{c,atom,[mountpoint],unknown},mandatory,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}},{{c,atom,[password],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}},{{c,atom,[peerhost],unknown},mandatory,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown}},{{c,atom,[protocol],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[sockport],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[username],unknown},mandatory,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}},{{c,atom,[ws_cookie],unknown},optional,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}},{{c,atom,[zone],unknown},mandatory,{c,atom,any,unknown}}],{c,atom,any,unknown},any},unknown}]},{emqx_bridge_proto_v1,stop_bridges_to_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_node_rebalance_proto_v1,enable_rebalance_agent,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,identifier,[pid],unknown}]},{emqx_node_rebalance_proto_v1,connection_counts,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_mgmt_api_plugins,get_plugins,0} => {{c,tuple,[{c,atom,any,unknown},{c,list,[{c,map,{[],any,any},unknown},{c,nil,[],unknown}],unknown}],{2,any}},[]},{emqx_proto_v2,clean_authz_cache,2} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}]},{emqx_bridge_proto_v3,lookup_from_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_mgmt_api_trace,read_trace_file,3} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[eof],unknown},{c,union,[{c,atom,[undefined],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown}],{2,{c,atom,[eof],unknown}}},{c,tuple,[{c,atom,[error],unknown},{c,union,[{c,atom,any,unknown},none,none,none,none,none,{c,tuple,[{c,atom,[no_translation],unknown},{c,atom,[unicode],unknown},{c,atom,[latin1],unknown}],{3,{c,atom,[no_translation],unknown}}},none,none,none],unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,binary,[8,0],unknown},any,any]},{emqx_gateway_cm,do_set_chan_info,4} => {{c,atom,[false,true],unknown},[any,any,any,any]},{emqx_resource_proto_v1,create_dry_run,2} => {any,[{c,atom,any,unknown},any]},{emqx_broker_proto_v1,forward,3} => {any,[{c,atom,any,unknown},{c,binary,[8,0],unknown},{c,tuple,[{c,atom,[delivery],unknown},{c,identifier,[pid],unknown},{c,tuple,[{c,atom,[message],unknown},{c,binary,[8,0],unknown},any,{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,map,{[],{c,atom,any,unknown},{c,atom,[false,true],unknown}},unknown},{c,map,{[{{c,atom,[allow_publish],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[peerhost],unknown},optional,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown}},{{c,atom,[properties],unknown},optional,{c,map,{[],{c,atom,any,unknown},any},unknown}},{{c,atom,[proto_ver],unknown},optional,{c,union,[none,{c,binary,[8,0],unknown},none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown}},{{c,atom,[protocol],unknown},optional,{c,atom,any,unknown}},{{c,atom,[username],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}}],{c,atom,any,unknown},any},unknown},{c,binary,[8,0],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},{c,number,{int_rng,0,255},integer},none,none,none,none],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},none,none,none,none,none],unknown},{c,number,any,integer},any],{10,{c,atom,[message],unknown}}}],{3,{c,atom,[delivery],unknown}}}]},{emqx_node_rebalance_evacuation,stop,0} => {any,[]},{emqx_bridge_proto_v1,restart_bridges_to_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_management_proto_v2,unsubscribe,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,binary,[8,0],unknown}]},{emqx_gateway_api_listeners,do_listeners_cluster_status,1} => {{c,map,{[],any,any},unknown},[{c,list,[any,{c,nil,[],unknown}],unknown}]},{emqx_proto_v2,are_running,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_retainer_proto_v2,wait_dispatch_complete,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown}]},{emqx_bridge_proto_v3,restart_bridges_to_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_node_rebalance_api_proto_v1,node_rebalance_start,2} => {any,[{c,atom,any,unknown},{c,map,{[{{c,atom,[abs_conn_threshold],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[abs_sess_threshold],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[conn_evict_rate],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[nodes],unknown},optional,{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}},{{c,atom,[rel_conn_threshold],unknown},optional,{c,number,any,unknown}},{{c,atom,[rel_sess_threshold],unknown},optional,{c,number,any,unknown}},{{c,atom,[sess_evict_rate],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[wait_health_check],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[wait_takeover],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}}],none,none},unknown}]},{emqx,get_config,2} => {any,[any,any]},{emqx_mgmt_trace_proto_v2,trace_file_detail,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[{c,atom,any,unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},{c,number,{int_rng,0,1114111},integer},none,none,none,none],unknown},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_bridge_proto_v2,stop_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_shared_sub_proto_v1,dispatch_with_ack,5} => {any,[{c,identifier,[pid],unknown},any,{c,binary,[8,0],unknown},{c,tuple,[{c,atom,[message],unknown},{c,binary,[8,0],unknown},any,{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,map,{[],{c,atom,any,unknown},{c,atom,[false,true],unknown}},unknown},{c,map,{[{{c,atom,[allow_publish],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[peerhost],unknown},optional,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown}},{{c,atom,[properties],unknown},optional,{c,map,{[],{c,atom,any,unknown},any},unknown}},{{c,atom,[proto_ver],unknown},optional,{c,union,[none,{c,binary,[8,0],unknown},none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown}},{{c,atom,[protocol],unknown},optional,{c,atom,any,unknown}},{{c,atom,[username],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}}],{c,atom,any,unknown},any},unknown},{c,binary,[8,0],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},{c,number,{int_rng,0,255},integer},none,none,none,none],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},none,none,none,none,none],unknown},{c,number,any,integer},any],{10,{c,atom,[message],unknown}}},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown}]},{emqx_gateway_http_proto_v1,get_cluster_status,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,atom,any,unknown}]},{emqx_management_proto_v3,list_subscriptions,1} => {any,[{c,atom,any,unknown}]},{emqx_cm_proto_v1,get_chan_stats,2} => {any,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_gateway_cm_proto_v1,takeover_session,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_conf_proto_v2,reset,2} => {any,[{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_node_rebalance_proto_v1,disconnected_session_counts,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{erlang,send,2} => {any,[any,any]},{emqx_cm_proto_v1,get_chan_info,2} => {any,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_gateway_cm_proto_v1,call,4} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown},any]},{emqx_eviction_agent,evict_connections,1} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},{c,atom,[disabled],unknown}],{2,{c,atom,[error],unknown}}},none,none,none],unknown},[any]},{emqx_dashboard_monitor,do_sample,2} => {any,[{c,atom,any,unknown},any]},{emqx_session_router,resume_end,2} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,list,[{c,tuple,any,{any,any}},{c,nil,[],unknown}],unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,identifier,[pid],unknown},{c,binary,[8,0],unknown}]},{emqx_node_rebalance,disconnected_session_count,0} => {{c,tuple,[{c,atom,[ok],unknown},any],{2,{c,atom,[ok],unknown}}},[]},{emqx_proto_v2,delete_all_deactivated_alarms,1} => {any,[{c,atom,any,unknown}]},{emqx_cm,do_get_chann_conn_mod,2} => {any,[any,any]},{emqx_exhook_mgr,server_hooks_metrics,1} => {any,[any]},{emqx_node_rebalance_status_proto_v1,local_status,1} => {any,[{c,atom,any,unknown}]},{emqx_alarm,delete_all_deactivated_alarms,0} => {any,[]},{emqx_proto_v1,deactivate_alarm,2} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}]},{emqx_bridge_proto_v1,restart_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_mgmt_cluster_proto_v1,invite_node,2} => {any,[{c,atom,any,unknown},{c,atom,any,unknown}]},{emqx_topic_metrics,metrics,1} => {{c,union,[none,none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},{c,atom,[topic_not_found],unknown}],{2,{c,atom,[error],unknown}}},none,none,{c,map,{[{{c,atom,[create_time],unknown},mandatory,any},{{c,atom,[metrics],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[reset_time],unknown},optional,any},{{c,atom,[topic],unknown},mandatory,any}],none,none},unknown}],unknown},[any]},{emqx_bridge_proto_v4,get_metrics_from_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_proto_v2,get_alarms,2} => {any,[{c,atom,any,unknown},{c,atom,[activated,all,deactivated],unknown}]},{emqx_bridge_proto_v2,lookup_from_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_gateway_cm,do_call,5} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown},any,any]},{emqx_management_proto_v1,list_listeners,1} => {any,[{c,atom,any,unknown}]},{emqx_bridge_proto_v2,restart_bridges_to_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_ft_storage_fs_proxy,list_local,2} => {any,[any,any]},{emqx_gateway_cm_proto_v1,lookup_by_clientid,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}]},{emqx_conf_proto_v1,get_all,1} => {any,[{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],unknown}]}}}. diff --git a/apps/emqx/test/emqx_static_checks_data/5.3.bpapi b/apps/emqx/test/emqx_static_checks_data/5.3.bpapi deleted file mode 100644 index 0f5f6b76d..000000000 --- a/apps/emqx/test/emqx_static_checks_data/5.3.bpapi +++ /dev/null @@ -1 +0,0 @@ -#{api => #{{emqx_node_rebalance,2} => #{calls => [{{emqx_node_rebalance_proto_v2,purge_sessions,['Nodes','Count']},{emqx_eviction_agent,purge_sessions,['Count']}},{{emqx_node_rebalance_proto_v2,disable_rebalance_agent,['Nodes','OwnerPid','Kind']},{emqx_node_rebalance_agent,disable,['OwnerPid','Kind']}},{{emqx_node_rebalance_proto_v2,enable_rebalance_agent,['Nodes','OwnerPid','Kind']},{emqx_node_rebalance_agent,enable,['OwnerPid','Kind']}},{{emqx_node_rebalance_proto_v2,disconnected_session_counts,['Nodes']},{emqx_node_rebalance,disconnected_session_count,[]}},{{emqx_node_rebalance_proto_v2,disable_rebalance_agent,['Nodes','OwnerPid']},{emqx_node_rebalance_agent,disable,['OwnerPid']}},{{emqx_node_rebalance_proto_v2,enable_rebalance_agent,['Nodes','OwnerPid']},{emqx_node_rebalance_agent,enable,['OwnerPid']}},{{emqx_node_rebalance_proto_v2,session_counts,['Nodes']},{emqx_node_rebalance,session_count,[]}},{{emqx_node_rebalance_proto_v2,connection_counts,['Nodes']},{emqx_node_rebalance,connection_count,[]}},{{emqx_node_rebalance_proto_v2,evict_sessions,['Nodes','Count','RecipientNodes','ConnState']},{emqx_eviction_agent,evict_sessions,['Count','RecipientNodes','ConnState']}},{{emqx_node_rebalance_proto_v2,evict_connections,['Nodes','Count']},{emqx_eviction_agent,evict_connections,['Count']}},{{emqx_node_rebalance_proto_v2,available_nodes,['Nodes']},{emqx_node_rebalance,is_node_available,[]}}],casts => []},{emqx_node_rebalance_purge,1} => #{calls => [{{emqx_node_rebalance_purge_proto_v1,stop,['Nodes']},{emqx_node_rebalance_purge,stop,[]}},{{emqx_node_rebalance_purge_proto_v1,start,['Nodes','Opts']},{emqx_node_rebalance_purge,start,['Opts']}}],casts => []},{emqx_authn,1} => #{calls => [{{emqx_authn_proto_v1,lookup_from_all_nodes,['Nodes','ChainName','AuthenticatorID']},{emqx_authn_api,lookup_from_local_node,['ChainName','AuthenticatorID']}}],casts => []},{emqx_persistent_session_ds,1} => #{calls => [{{emqx_persistent_session_ds_proto_v1,close_all_iterators,['Nodes','DSSessionID']},{emqx_persistent_session_ds,do_ensure_all_iterators_closed,['DSSessionID']}},{{emqx_persistent_session_ds_proto_v1,close_iterator,['Nodes','IteratorID']},{emqx_persistent_session_ds,do_ensure_iterator_closed,['IteratorID']}},{{emqx_persistent_session_ds_proto_v1,open_iterator,['Nodes','TopicFilter','StartMS','IteratorID']},{emqx_persistent_session_ds,do_open_iterator,['TopicFilter','StartMS','IteratorID']}}],casts => []},{emqx_delayed,1} => #{calls => [{{emqx_delayed_proto_v1,delete_delayed_message,['Node','Id']},{emqx_delayed,delete_delayed_message,['Id']}},{{emqx_delayed_proto_v1,get_delayed_message,['Node','Id']},{emqx_delayed,get_delayed_message,['Id']}}],casts => []},{emqx_conf,2} => #{calls => [{{emqx_conf_proto_v2,get_override_config_file,['Nodes']},{emqx_conf_app,get_override_config_file,[]}},{{emqx_conf_proto_v2,reset,['Node','KeyPath','Opts']},{emqx,reset_config,['KeyPath','Opts']}},{{emqx_conf_proto_v2,reset,['KeyPath','Opts']},{emqx,reset_config,['KeyPath','Opts']}},{{emqx_conf_proto_v2,remove_config,['Node','KeyPath','Opts']},{emqx,remove_config,['KeyPath','Opts']}},{{emqx_conf_proto_v2,remove_config,['KeyPath','Opts']},{emqx,remove_config,['KeyPath','Opts']}},{{emqx_conf_proto_v2,update,['Node','KeyPath','UpdateReq','Opts']},{emqx,update_config,['KeyPath','UpdateReq','Opts']}},{{emqx_conf_proto_v2,update,['KeyPath','UpdateReq','Opts']},{emqx,update_config,['KeyPath','UpdateReq','Opts']}},{{emqx_conf_proto_v2,get_all,['KeyPath']},{emqx_conf,get_node_and_config,['KeyPath']}},{{emqx_conf_proto_v2,get_config,['Node','KeyPath','Default']},{emqx,get_config,['KeyPath','Default']}},{{emqx_conf_proto_v2,get_config,['Node','KeyPath']},{emqx,get_config,['KeyPath']}},{{emqx_conf_proto_v2,sync_data_from_node,['Node']},{emqx_conf_app,sync_data_from_node,[]}}],casts => []},{emqx_license,1} => #{calls => [{{emqx_license_proto_v1,remote_connection_counts,['Nodes']},{emqx_license_resources,local_connection_count,[]}}],casts => []},{emqx_delayed,2} => #{calls => [{{emqx_delayed_proto_v2,clear_all,['Nodes']},{emqx_delayed,clear_all_local,[]}},{{emqx_delayed_proto_v2,delete_delayed_message,['Node','Id']},{emqx_delayed,delete_delayed_message,['Id']}},{{emqx_delayed_proto_v2,get_delayed_message,['Node','Id']},{emqx_delayed,get_delayed_message,['Id']}}],casts => []},{emqx_gateway_api_listeners,1} => #{calls => [{{emqx_gateway_api_listeners_proto_v1,listeners_cluster_status,['Nodes','Listeners']},{emqx_gateway_api_listeners,do_listeners_cluster_status,['Listeners']}}],casts => []},{emqx_node_rebalance,1} => #{calls => [{{emqx_node_rebalance_proto_v1,disconnected_session_counts,['Nodes']},{emqx_node_rebalance,disconnected_session_count,[]}},{{emqx_node_rebalance_proto_v1,disable_rebalance_agent,['Nodes','OwnerPid']},{emqx_node_rebalance_agent,disable,['OwnerPid']}},{{emqx_node_rebalance_proto_v1,enable_rebalance_agent,['Nodes','OwnerPid']},{emqx_node_rebalance_agent,enable,['OwnerPid']}},{{emqx_node_rebalance_proto_v1,session_counts,['Nodes']},{emqx_node_rebalance,session_count,[]}},{{emqx_node_rebalance_proto_v1,connection_counts,['Nodes']},{emqx_node_rebalance,connection_count,[]}},{{emqx_node_rebalance_proto_v1,evict_sessions,['Nodes','Count','RecipientNodes','ConnState']},{emqx_eviction_agent,evict_sessions,['Count','RecipientNodes','ConnState']}},{{emqx_node_rebalance_proto_v1,evict_connections,['Nodes','Count']},{emqx_eviction_agent,evict_connections,['Count']}},{{emqx_node_rebalance_proto_v1,available_nodes,['Nodes']},{emqx_node_rebalance,is_node_available,[]}}],casts => []},{emqx_mgmt_api_plugins,1} => #{calls => [{{emqx_mgmt_api_plugins_proto_v1,ensure_action,['Name','Action']},{emqx_mgmt_api_plugins,ensure_action,['Name','Action']}},{{emqx_mgmt_api_plugins_proto_v1,delete_package,['Name']},{emqx_mgmt_api_plugins,delete_package,['Name']}},{{emqx_mgmt_api_plugins_proto_v1,describe_package,['Name']},{emqx_mgmt_api_plugins,describe_package,['Name']}},{{emqx_mgmt_api_plugins_proto_v1,install_package,['Filename','Bin']},{emqx_mgmt_api_plugins,install_package,['Filename','Bin']}},{{emqx_mgmt_api_plugins_proto_v1,get_plugins,[]},{emqx_mgmt_api_plugins,get_plugins,[]}}],casts => []},{emqx_management,4} => #{calls => [{{emqx_management_proto_v4,kickout_clients,['Node','ClientIds']},{emqx_mgmt,do_kickout_clients,['ClientIds']}},{{emqx_management_proto_v4,get_full_config,['Node']},{emqx_mgmt_api_configs,get_full_config,[]}},{{emqx_management_proto_v4,call_client,['Node','ClientId','Req']},{emqx_mgmt,do_call_client,['ClientId','Req']}},{{emqx_management_proto_v4,unsubscribe,['Node','ClientId','Topic']},{emqx_mgmt,do_unsubscribe,['ClientId','Topic']}},{{emqx_management_proto_v4,subscribe,['Node','ClientId','TopicTables']},{emqx_mgmt,do_subscribe,['ClientId','TopicTables']}},{{emqx_management_proto_v4,list_listeners,['Node']},{emqx_mgmt_api_listeners,do_list_listeners,[]}},{{emqx_management_proto_v4,list_subscriptions,['Node']},{emqx_mgmt,do_list_subscriptions,[]}},{{emqx_management_proto_v4,broker_info,['Nodes']},{emqx_mgmt,broker_info,[]}},{{emqx_management_proto_v4,node_info,['Nodes']},{emqx_mgmt,node_info,[]}},{{emqx_management_proto_v4,unsubscribe_batch,['Node','ClientId','Topics']},{emqx_mgmt,do_unsubscribe_batch,['ClientId','Topics']}}],casts => []},{emqx_mgmt_trace,2} => #{calls => [{{emqx_mgmt_trace_proto_v2,read_trace_file,['Node','Name','Position','Limit']},{emqx_mgmt_api_trace,read_trace_file,['Name','Position','Limit']}},{{emqx_mgmt_trace_proto_v2,trace_file_detail,['Nodes','File']},{emqx_trace,trace_file_detail,['File']}},{{emqx_mgmt_trace_proto_v2,trace_file,['Nodes','File']},{emqx_trace,trace_file,['File']}},{{emqx_mgmt_trace_proto_v2,get_trace_size,['Nodes']},{emqx_mgmt_api_trace,get_trace_size,[]}}],casts => []},{emqx_node_rebalance_status,2} => #{calls => [{{emqx_node_rebalance_status_proto_v2,purge_status,['Nodes']},{emqx_node_rebalance_status,purge_status,[]}},{{emqx_node_rebalance_status_proto_v2,evacuation_status,['Nodes']},{emqx_node_rebalance_status,evacuation_status,[]}},{{emqx_node_rebalance_status_proto_v2,rebalance_status,['Nodes']},{emqx_node_rebalance_status,rebalance_status,[]}},{{emqx_node_rebalance_status_proto_v2,local_status,['Node']},{emqx_node_rebalance_status,local_status,[]}}],casts => []},{emqx_bridge,1} => #{calls => [{{emqx_bridge_proto_v1,lookup_from_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_api,lookup_from_local_node,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v1,stop_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,stop,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v1,restart_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,restart,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v1,stop_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,stop,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v1,restart_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,restart,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v1,list_bridges,['Node']},{emqx_bridge,list,[]}}],casts => []},{emqx_mgmt_cluster,2} => #{calls => [{{emqx_mgmt_cluster_proto_v2,connected_replicants,['Nodes']},{emqx_mgmt_api_cluster,connected_replicants,[]}},{{emqx_mgmt_cluster_proto_v2,invite_node,['Node','Self']},{emqx_mgmt_api_cluster,join,['Self']}}],casts => []},{emqx_management,2} => #{calls => [{{emqx_management_proto_v2,get_full_config,['Node']},{emqx_mgmt_api_configs,get_full_config,[]}},{{emqx_management_proto_v2,call_client,['Node','ClientId','Req']},{emqx_mgmt,do_call_client,['ClientId','Req']}},{{emqx_management_proto_v2,unsubscribe,['Node','ClientId','Topic']},{emqx_mgmt,do_unsubscribe,['ClientId','Topic']}},{{emqx_management_proto_v2,subscribe,['Node','ClientId','TopicTables']},{emqx_mgmt,do_subscribe,['ClientId','TopicTables']}},{{emqx_management_proto_v2,list_listeners,['Node']},{emqx_mgmt_api_listeners,do_list_listeners,[]}},{{emqx_management_proto_v2,list_subscriptions,['Node']},{emqx_mgmt,do_list_subscriptions,[]}},{{emqx_management_proto_v2,broker_info,['Node']},{emqx_mgmt,broker_info,[]}},{{emqx_management_proto_v2,node_info,['Node']},{emqx_mgmt,node_info,[]}},{{emqx_management_proto_v2,unsubscribe_batch,['Node','ClientId','Topics']},{emqx_mgmt,do_unsubscribe_batch,['ClientId','Topics']}}],casts => []},{emqx,1} => #{calls => [{{emqx_proto_v1,delete_all_deactivated_alarms,['Node']},{emqx_alarm,delete_all_deactivated_alarms,[]}},{{emqx_proto_v1,deactivate_alarm,['Node','Name']},{emqx_alarm,deactivate,['Name']}},{{emqx_proto_v1,clean_pem_cache,['Node']},{ssl_pem_cache,clear,[]}},{{emqx_proto_v1,clean_authz_cache,['Node']},{emqx_authz_cache,drain_cache,[]}},{{emqx_proto_v1,clean_authz_cache,['Node','ClientId']},{emqx_authz_cache,drain_cache,['ClientId']}},{{emqx_proto_v1,get_metrics,['Node']},{emqx_metrics,all,[]}},{{emqx_proto_v1,get_stats,['Node']},{emqx_stats,getstats,[]}},{{emqx_proto_v1,get_alarms,['Node','Type']},{emqx_alarm,get_alarms,['Type']}},{{emqx_proto_v1,is_running,['Node']},{emqx,is_running,[]}}],casts => []},{emqx_shared_sub,1} => #{calls => [{{emqx_shared_sub_proto_v1,dispatch_with_ack,['Pid','Group','Topic','Msg','Timeout']},{emqx_shared_sub,do_dispatch_with_ack,['Pid','Group','Topic','Msg']}}],casts => [{{emqx_shared_sub_proto_v1,send,['Node','Pid','Topic','Msg']},{erlang,send,['Pid','Msg']}}]},{emqx_eviction_agent,1} => #{calls => [{{emqx_eviction_agent_proto_v1,evict_session_channel,['Node','ClientId','ConnInfo','ClientInfo']},{emqx_eviction_agent,evict_session_channel,['ClientId','ConnInfo','ClientInfo']}}],casts => []},{emqx_mgmt_cluster,1} => #{calls => [{{emqx_mgmt_cluster_proto_v1,invite_node,['Node','Self']},{emqx_mgmt_api_cluster,join,['Self']}}],casts => []},{emqx_metrics,1} => #{calls => [{{emqx_metrics_proto_v1,get_metrics,['Nodes','HandlerName','MetricId','Timeout']},{emqx_metrics_worker,get_metrics,['HandlerName','MetricId']}}],casts => []},{emqx_topic_metrics,1} => #{calls => [{{emqx_topic_metrics_proto_v1,reset,['Nodes','Topic']},{emqx_topic_metrics,reset,['Topic']}},{{emqx_topic_metrics_proto_v1,reset,['Nodes']},{emqx_topic_metrics,reset,[]}},{{emqx_topic_metrics_proto_v1,metrics,['Nodes','Topic']},{emqx_topic_metrics,metrics,['Topic']}},{{emqx_topic_metrics_proto_v1,metrics,['Nodes']},{emqx_topic_metrics,metrics,[]}}],casts => []},{emqx_management,3} => #{calls => [{{emqx_management_proto_v3,get_full_config,['Node']},{emqx_mgmt_api_configs,get_full_config,[]}},{{emqx_management_proto_v3,call_client,['Node','ClientId','Req']},{emqx_mgmt,do_call_client,['ClientId','Req']}},{{emqx_management_proto_v3,unsubscribe,['Node','ClientId','Topic']},{emqx_mgmt,do_unsubscribe,['ClientId','Topic']}},{{emqx_management_proto_v3,subscribe,['Node','ClientId','TopicTables']},{emqx_mgmt,do_subscribe,['ClientId','TopicTables']}},{{emqx_management_proto_v3,list_listeners,['Node']},{emqx_mgmt_api_listeners,do_list_listeners,[]}},{{emqx_management_proto_v3,list_subscriptions,['Node']},{emqx_mgmt,do_list_subscriptions,[]}},{{emqx_management_proto_v3,broker_info,['Nodes']},{emqx_mgmt,broker_info,[]}},{{emqx_management_proto_v3,node_info,['Nodes']},{emqx_mgmt,node_info,[]}},{{emqx_management_proto_v3,unsubscribe_batch,['Node','ClientId','Topics']},{emqx_mgmt,do_unsubscribe_batch,['ClientId','Topics']}}],casts => []},{emqx_plugins,1} => #{calls => [{{emqx_plugins_proto_v1,get_tar,['Node','NameVsn','Timeout']},{emqx_plugins,get_tar,['NameVsn']}}],casts => []},{emqx_resource,1} => #{calls => [{{emqx_resource_proto_v1,reset_metrics,['ResId']},{emqx_resource,reset_metrics_local,['ResId']}},{{emqx_resource_proto_v1,remove,['ResId']},{emqx_resource,remove_local,['ResId']}},{{emqx_resource_proto_v1,recreate,['ResId','ResourceType','Config','Opts']},{emqx_resource,recreate_local,['ResId','ResourceType','Config','Opts']}},{{emqx_resource_proto_v1,create_dry_run,['ResourceType','Config']},{emqx_resource,create_dry_run_local,['ResourceType','Config']}},{{emqx_resource_proto_v1,create,['ResId','Group','ResourceType','Config','Opts']},{emqx_resource,create_local,['ResId','Group','ResourceType','Config','Opts']}}],casts => []},{emqx_conf,3} => #{calls => [{{emqx_conf_proto_v3,get_hocon_config,['Node','Key']},{emqx_conf_cli,get_config,['Key']}},{{emqx_conf_proto_v3,get_hocon_config,['Node']},{emqx_conf_cli,get_config,[]}},{{emqx_conf_proto_v3,get_override_config_file,['Nodes']},{emqx_conf_app,get_override_config_file,[]}},{{emqx_conf_proto_v3,reset,['Node','KeyPath','Opts']},{emqx,reset_config,['KeyPath','Opts']}},{{emqx_conf_proto_v3,reset,['KeyPath','Opts']},{emqx,reset_config,['KeyPath','Opts']}},{{emqx_conf_proto_v3,remove_config,['Node','KeyPath','Opts']},{emqx,remove_config,['KeyPath','Opts']}},{{emqx_conf_proto_v3,remove_config,['KeyPath','Opts']},{emqx,remove_config,['KeyPath','Opts']}},{{emqx_conf_proto_v3,update,['Node','KeyPath','UpdateReq','Opts']},{emqx,update_config,['KeyPath','UpdateReq','Opts']}},{{emqx_conf_proto_v3,update,['KeyPath','UpdateReq','Opts']},{emqx,update_config,['KeyPath','UpdateReq','Opts']}},{{emqx_conf_proto_v3,get_all,['KeyPath']},{emqx_conf,get_node_and_config,['KeyPath']}},{{emqx_conf_proto_v3,get_config,['Node','KeyPath','Default']},{emqx,get_config,['KeyPath','Default']}},{{emqx_conf_proto_v3,get_config,['Node','KeyPath']},{emqx,get_config,['KeyPath']}},{{emqx_conf_proto_v3,sync_data_from_node,['Node']},{emqx_conf_app,sync_data_from_node,[]}}],casts => []},{emqx,2} => #{calls => [{{emqx_proto_v2,delete_all_deactivated_alarms,['Node']},{emqx_alarm,delete_all_deactivated_alarms,[]}},{{emqx_proto_v2,deactivate_alarm,['Node','Name']},{emqx_alarm,deactivate,['Name']}},{{emqx_proto_v2,clean_pem_cache,['Node']},{ssl_pem_cache,clear,[]}},{{emqx_proto_v2,clean_authz_cache,['Node']},{emqx_authz_cache,drain_cache,[]}},{{emqx_proto_v2,clean_authz_cache,['Node','ClientId']},{emqx_authz_cache,drain_cache,['ClientId']}},{{emqx_proto_v2,get_metrics,['Node']},{emqx_metrics,all,[]}},{{emqx_proto_v2,get_stats,['Node']},{emqx_stats,getstats,[]}},{{emqx_proto_v2,get_alarms,['Node','Type']},{emqx_alarm,get_alarms,['Type']}},{{emqx_proto_v2,are_running,['Nodes']},{emqx,is_running,[]}},{{emqx_proto_v2,is_running,['Node']},{emqx,is_running,[]}}],casts => []},{emqx_node_rebalance_status,1} => #{calls => [{{emqx_node_rebalance_status_proto_v1,evacuation_status,['Nodes']},{emqx_node_rebalance_status,evacuation_status,[]}},{{emqx_node_rebalance_status_proto_v1,rebalance_status,['Nodes']},{emqx_node_rebalance_status,rebalance_status,[]}},{{emqx_node_rebalance_status_proto_v1,local_status,['Node']},{emqx_node_rebalance_status,local_status,[]}}],casts => []},{emqx_gateway_http,1} => #{calls => [{{emqx_gateway_http_proto_v1,get_cluster_status,['Nodes','GwName']},{emqx_gateway_http,gateway_status,['GwName']}}],casts => []},{emqx_eviction_agent,2} => #{calls => [{{emqx_eviction_agent_proto_v2,all_channels_count,['Nodes','Timeout']},{emqx_eviction_agent,all_local_channels_count,[]}},{{emqx_eviction_agent_proto_v2,evict_session_channel,['Node','ClientId','ConnInfo','ClientInfo']},{emqx_eviction_agent,evict_session_channel,['ClientId','ConnInfo','ClientInfo']}}],casts => []},{emqx_conf,1} => #{calls => [{{emqx_conf_proto_v1,get_override_config_file,['Nodes']},{emqx_conf_app,get_override_config_file,[]}},{{emqx_conf_proto_v1,reset,['Node','KeyPath','Opts']},{emqx,reset_config,['KeyPath','Opts']}},{{emqx_conf_proto_v1,reset,['KeyPath','Opts']},{emqx,reset_config,['KeyPath','Opts']}},{{emqx_conf_proto_v1,remove_config,['Node','KeyPath','Opts']},{emqx,remove_config,['KeyPath','Opts']}},{{emqx_conf_proto_v1,remove_config,['KeyPath','Opts']},{emqx,remove_config,['KeyPath','Opts']}},{{emqx_conf_proto_v1,update,['Node','KeyPath','UpdateReq','Opts']},{emqx,update_config,['KeyPath','UpdateReq','Opts']}},{{emqx_conf_proto_v1,update,['KeyPath','UpdateReq','Opts']},{emqx,update_config,['KeyPath','UpdateReq','Opts']}},{{emqx_conf_proto_v1,get_all,['KeyPath']},{emqx_conf,get_node_and_config,['KeyPath']}},{{emqx_conf_proto_v1,get_config,['Node','KeyPath','Default']},{emqx,get_config,['KeyPath','Default']}},{{emqx_conf_proto_v1,get_config,['Node','KeyPath']},{emqx,get_config,['KeyPath']}}],casts => []},{emqx_cm,1} => #{calls => [{{emqx_cm_proto_v1,kick_session,['Action','ClientId','ChanPid']},{emqx_cm,do_kick_session,['Action','ClientId','ChanPid']}},{{emqx_cm_proto_v1,takeover_session,['ClientId','ChanPid']},{emqx_cm,takeover_session,['ClientId','ChanPid']}},{{emqx_cm_proto_v1,get_chann_conn_mod,['ClientId','ChanPid']},{emqx_cm,do_get_chann_conn_mod,['ClientId','ChanPid']}},{{emqx_cm_proto_v1,get_chan_info,['ClientId','ChanPid']},{emqx_cm,do_get_chan_info,['ClientId','ChanPid']}},{{emqx_cm_proto_v1,get_chan_stats,['ClientId','ChanPid']},{emqx_cm,do_get_chan_stats,['ClientId','ChanPid']}},{{emqx_cm_proto_v1,lookup_client,['Node','Key']},{emqx_cm,lookup_client,['Key']}},{{emqx_cm_proto_v1,kickout_client,['Node','ClientId']},{emqx_cm,kick_session,['ClientId']}}],casts => []},{emqx_management,1} => #{calls => [{{emqx_management_proto_v1,get_full_config,['Node']},{emqx_mgmt_api_configs,get_full_config,[]}},{{emqx_management_proto_v1,call_client,['Node','ClientId','Req']},{emqx_mgmt,do_call_client,['ClientId','Req']}},{{emqx_management_proto_v1,unsubscribe,['Node','ClientId','Topic']},{emqx_mgmt,do_unsubscribe,['ClientId','Topic']}},{{emqx_management_proto_v1,subscribe,['Node','ClientId','TopicTables']},{emqx_mgmt,do_subscribe,['ClientId','TopicTables']}},{{emqx_management_proto_v1,list_listeners,['Node']},{emqx_mgmt_api_listeners,do_list_listeners,[]}},{{emqx_management_proto_v1,list_subscriptions,['Node']},{emqx_mgmt,do_list_subscriptions,[]}},{{emqx_management_proto_v1,broker_info,['Node']},{emqx_mgmt,broker_info,[]}},{{emqx_management_proto_v1,node_info,['Node']},{emqx_mgmt,node_info,[]}}],casts => []},{emqx_slow_subs,1} => #{calls => [{{emqx_slow_subs_proto_v1,get_history,['Nodes']},{emqx_slow_subs_api,get_history,[]}},{{emqx_slow_subs_proto_v1,clear_history,['Nodes']},{emqx_slow_subs,clear_history,[]}}],casts => []},{emqx_ft_storage_fs_reader,1} => #{calls => [{{emqx_ft_storage_fs_reader_proto_v1,read,['Node','Pid','Bytes']},{emqx_ft_storage_fs_reader,read,['Pid','Bytes']}}],casts => []},{emqx_prometheus,1} => #{calls => [{{emqx_prometheus_proto_v1,stop,['Nodes']},{emqx_prometheus,do_stop,[]}},{{emqx_prometheus_proto_v1,start,['Nodes']},{emqx_prometheus,do_start,[]}}],casts => []},{emqx_cm,2} => #{calls => [{{emqx_cm_proto_v2,kick_session,['Action','ClientId','ChanPid']},{emqx_cm,do_kick_session,['Action','ClientId','ChanPid']}},{{emqx_cm_proto_v2,takeover_finish,['ConnMod','ChanPid']},{emqx_cm,takeover_finish,['ConnMod','ChanPid']}},{{emqx_cm_proto_v2,takeover_session,['ClientId','ChanPid']},{emqx_cm,takeover_session,['ClientId','ChanPid']}},{{emqx_cm_proto_v2,get_chann_conn_mod,['ClientId','ChanPid']},{emqx_cm,do_get_chann_conn_mod,['ClientId','ChanPid']}},{{emqx_cm_proto_v2,get_chan_info,['ClientId','ChanPid']},{emqx_cm,do_get_chan_info,['ClientId','ChanPid']}},{{emqx_cm_proto_v2,get_chan_stats,['ClientId','ChanPid']},{emqx_cm,do_get_chan_stats,['ClientId','ChanPid']}},{{emqx_cm_proto_v2,lookup_client,['Node','Key']},{emqx_cm,lookup_client,['Key']}},{{emqx_cm_proto_v2,kickout_client,['Node','ClientId']},{emqx_cm,kick_session,['ClientId']}}],casts => []},{emqx_dashboard,1} => #{calls => [{{emqx_dashboard_proto_v1,current_rate,['Node']},{emqx_dashboard_monitor,current_rate,['Node']}},{{emqx_dashboard_proto_v1,do_sample,['Node','Latest']},{emqx_dashboard_monitor,do_sample,['Node','Latest']}}],casts => []},{emqx_mgmt_api_plugins,2} => #{calls => [{{emqx_mgmt_api_plugins_proto_v2,ensure_action,['Name','Action']},{emqx_mgmt_api_plugins,ensure_action,['Name','Action']}},{{emqx_mgmt_api_plugins_proto_v2,delete_package,['Name']},{emqx_mgmt_api_plugins,delete_package,['Name']}},{{emqx_mgmt_api_plugins_proto_v2,describe_package,['Nodes','Name']},{emqx_mgmt_api_plugins,describe_package,['Name']}},{{emqx_mgmt_api_plugins_proto_v2,install_package,['Nodes','Filename','Bin']},{emqx_mgmt_api_plugins,install_package,['Filename','Bin']}},{{emqx_mgmt_api_plugins_proto_v2,get_plugins,['Nodes']},{emqx_mgmt_api_plugins,get_plugins,[]}}],casts => []},{emqx_authz,1} => #{calls => [{{emqx_authz_proto_v1,lookup_from_all_nodes,['Nodes','Type']},{emqx_authz_api_sources,lookup_from_local_node,['Type']}}],casts => []},{emqx_ft_storage_exporter_fs,1} => #{calls => [{{emqx_ft_storage_exporter_fs_proto_v1,read_export_file,['Node','Filepath','CallerPid']},{emqx_ft_storage_exporter_fs_proxy,read_export_file_local,['Filepath','CallerPid']}},{{emqx_ft_storage_exporter_fs_proto_v1,list_exports,['Nodes','Query']},{emqx_ft_storage_exporter_fs_proxy,list_exports_local,['Query']}}],casts => []},{emqx_node_rebalance_evacuation,1} => #{calls => [{{emqx_node_rebalance_evacuation_proto_v1,available_nodes,['Nodes']},{emqx_node_rebalance_evacuation,is_node_available,[]}}],casts => []},{emqx_node_rebalance_api,2} => #{calls => [{{emqx_node_rebalance_api_proto_v2,node_rebalance_purge_stop,['Node']},{emqx_node_rebalance_purge,stop,[]}},{{emqx_node_rebalance_api_proto_v2,node_rebalance_purge_start,['Node','Opts']},{emqx_node_rebalance_purge,start,['Opts']}},{{emqx_node_rebalance_api_proto_v2,node_rebalance_stop,['Node']},{emqx_node_rebalance,stop,[]}},{{emqx_node_rebalance_api_proto_v2,node_rebalance_start,['Node','Opts']},{emqx_node_rebalance,start,['Opts']}},{{emqx_node_rebalance_api_proto_v2,node_rebalance_evacuation_stop,['Node']},{emqx_node_rebalance_evacuation,stop,[]}},{{emqx_node_rebalance_api_proto_v2,node_rebalance_evacuation_start,['Node','Opts']},{emqx_node_rebalance_evacuation,start,['Opts']}}],casts => []},{emqx_retainer,1} => #{calls => [{{emqx_retainer_proto_v1,wait_dispatch_complete,['Nodes','Timeout']},{emqx_retainer_dispatcher,wait_dispatch_complete,['Timeout']}}],casts => []},{emqx_ft_storage_fs,1} => #{calls => [{{emqx_ft_storage_fs_proto_v1,list_assemblers,['Nodes','Transfer']},{emqx_ft_storage_fs_proxy,lookup_local_assembler,['Transfer']}},{{emqx_ft_storage_fs_proto_v1,pread,['Node','Transfer','Frag','Offset','Size']},{emqx_ft_storage_fs_proxy,pread_local,['Transfer','Frag','Offset','Size']}},{{emqx_ft_storage_fs_proto_v1,multilist,['Nodes','Transfer','What']},{emqx_ft_storage_fs_proxy,list_local,['Transfer','What']}}],casts => []},{emqx_node_rebalance_api,1} => #{calls => [{{emqx_node_rebalance_api_proto_v1,node_rebalance_stop,['Node']},{emqx_node_rebalance,stop,[]}},{{emqx_node_rebalance_api_proto_v1,node_rebalance_start,['Node','Opts']},{emqx_node_rebalance,start,['Opts']}},{{emqx_node_rebalance_api_proto_v1,node_rebalance_evacuation_stop,['Node']},{emqx_node_rebalance_evacuation,stop,[]}},{{emqx_node_rebalance_api_proto_v1,node_rebalance_evacuation_start,['Node','Opts']},{emqx_node_rebalance_evacuation,start,['Opts']}}],casts => []},{emqx_bridge,3} => #{calls => [{{emqx_bridge_proto_v3,lookup_from_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_api,lookup_from_local_node,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v3,stop_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,stop,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v3,start_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,start,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v3,restart_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,restart,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v3,stop_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,stop,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v3,start_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,start,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v3,restart_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,restart,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v3,list_bridges_on_nodes,['Nodes']},{emqx_bridge,list,[]}},{{emqx_bridge_proto_v3,list_bridges,['Node']},{emqx_bridge,list,[]}}],casts => []},{emqx_license,2} => #{calls => [{{emqx_license_proto_v2,remote_connection_counts,['Nodes']},{emqx_license_resources,local_connection_count,[]}}],casts => []},{emqx_rule_engine,1} => #{calls => [{{emqx_rule_engine_proto_v1,reset_metrics,['RuleId']},{emqx_rule_engine,reset_metrics_for_rule,['RuleId']}}],casts => []},{emqx_bridge,4} => #{calls => [{{emqx_bridge_proto_v4,get_metrics_from_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_api,get_metrics_from_local_node,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v4,lookup_from_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_api,lookup_from_local_node,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v4,stop_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,stop,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v4,start_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,start,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v4,restart_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,restart,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v4,stop_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,stop,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v4,start_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,start,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v4,restart_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,restart,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v4,list_bridges_on_nodes,['Nodes']},{emqx_bridge,list,[]}}],casts => []},{emqx_exhook,1} => #{calls => [{{emqx_exhook_proto_v1,server_hooks_metrics,['Nodes','Name']},{emqx_exhook_mgr,server_hooks_metrics,['Name']}},{{emqx_exhook_proto_v1,server_info,['Nodes','Name']},{emqx_exhook_mgr,server_info,['Name']}},{{emqx_exhook_proto_v1,all_servers_info,['Nodes']},{emqx_exhook_mgr,all_servers_info,[]}}],casts => []},{emqx_telemetry,1} => #{calls => [{{emqx_telemetry_proto_v1,get_cluster_uuid,['Node']},{emqx_telemetry,get_cluster_uuid,[]}},{{emqx_telemetry_proto_v1,get_node_uuid,['Node']},{emqx_telemetry,get_node_uuid,[]}}],casts => []},{emqx_broker,1} => #{calls => [{{emqx_broker_proto_v1,list_subscriptions_via_topic,['Node','Topic']},{emqx_broker,subscriptions_via_topic,['Topic']}},{{emqx_broker_proto_v1,list_client_subscriptions,['Node','ClientId']},{emqx_broker,subscriptions,['ClientId']}},{{emqx_broker_proto_v1,forward,['Node','Topic','Delivery']},{emqx_broker,dispatch,['Topic','Delivery']}}],casts => [{{emqx_broker_proto_v1,forward_async,['Node','Topic','Delivery']},{emqx_broker,dispatch,['Topic','Delivery']}}]},{emqx_retainer,2} => #{calls => [{{emqx_retainer_proto_v2,active_mnesia_indices,['Nodes']},{emqx_retainer_mnesia,active_indices,[]}},{{emqx_retainer_proto_v2,wait_dispatch_complete,['Nodes','Timeout']},{emqx_retainer_dispatcher,wait_dispatch_complete,['Timeout']}}],casts => []},{emqx_gateway_cm,1} => #{calls => [{{emqx_gateway_cm_proto_v1,cast,['GwName','ClientId','ChanPid','Req']},{emqx_gateway_cm,do_cast,['GwName','ClientId','ChanPid','Req']}},{{emqx_gateway_cm_proto_v1,call,['GwName','ClientId','ChanPid','Req']},{emqx_gateway_cm,do_call,['GwName','ClientId','ChanPid','Req']}},{{emqx_gateway_cm_proto_v1,call,['GwName','ClientId','ChanPid','Req','Timeout']},{emqx_gateway_cm,do_call,['GwName','ClientId','ChanPid','Req','Timeout']}},{{emqx_gateway_cm_proto_v1,takeover_session,['GwName','ClientId','ChanPid']},{emqx_gateway_cm,do_takeover_session,['GwName','ClientId','ChanPid']}},{{emqx_gateway_cm_proto_v1,get_chann_conn_mod,['GwName','ClientId','ChanPid']},{emqx_gateway_cm,do_get_chann_conn_mod,['GwName','ClientId','ChanPid']}},{{emqx_gateway_cm_proto_v1,kick_session,['GwName','Action','ClientId','ChanPid']},{emqx_gateway_cm,do_kick_session,['GwName','Action','ClientId','ChanPid']}},{{emqx_gateway_cm_proto_v1,set_chan_stats,['GwName','ClientId','ChanPid','Stats']},{emqx_gateway_cm,do_set_chan_stats,['GwName','ClientId','ChanPid','Stats']}},{{emqx_gateway_cm_proto_v1,get_chan_stats,['GwName','ClientId','ChanPid']},{emqx_gateway_cm,do_get_chan_stats,['GwName','ClientId','ChanPid']}},{{emqx_gateway_cm_proto_v1,set_chan_info,['GwName','ClientId','ChanPid','Infos']},{emqx_gateway_cm,do_set_chan_info,['GwName','ClientId','ChanPid','Infos']}},{{emqx_gateway_cm_proto_v1,get_chan_info,['GwName','ClientId','ChanPid']},{emqx_gateway_cm,do_get_chan_info,['GwName','ClientId','ChanPid']}},{{emqx_gateway_cm_proto_v1,lookup_by_clientid,['Nodes','GwName','ClientId']},{emqx_gateway_cm,do_lookup_by_clientid,['GwName','ClientId']}}],casts => []},{emqx_bridge,2} => #{calls => [{{emqx_bridge_proto_v2,lookup_from_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_api,lookup_from_local_node,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v2,stop_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,stop,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v2,start_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,start,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v2,restart_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,restart,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v2,stop_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,stop,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v2,start_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,start,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v2,restart_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,restart,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v2,list_bridges,['Node']},{emqx_bridge,list,[]}}],casts => []},{emqx_mgmt_trace,1} => #{calls => [{{emqx_mgmt_trace_proto_v1,read_trace_file,['Node','Name','Position','Limit']},{emqx_mgmt_api_trace,read_trace_file,['Name','Position','Limit']}},{{emqx_mgmt_trace_proto_v1,trace_file,['Nodes','File']},{emqx_trace,trace_file,['File']}},{{emqx_mgmt_trace_proto_v1,get_trace_size,['Nodes']},{emqx_mgmt_api_trace,get_trace_size,[]}}],casts => []}},release => "5.3",signatures => #{{emqx_broker,dispatch,2} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,atom,[no_subscribers,not_running],unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,number,{int_rng,0,pos_inf},integer}],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,binary,[8,0],unknown},{c,tuple,[{c,atom,[delivery],unknown},{c,identifier,[pid],unknown},{c,tuple,[{c,atom,[message],unknown},{c,binary,[8,0],unknown},any,{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,map,{[],{c,atom,any,unknown},{c,atom,[false,true],unknown}},unknown},{c,map,{[{{c,atom,[allow_publish],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[peerhost],unknown},optional,{c,tuple_set,[{4,[{c,tuple,[any,any,any,any],{4,any}}]},{8,[{c,tuple,[any,any,any,any,any,any,any,any],{8,any}}]}],unknown}},{{c,atom,[properties],unknown},optional,{c,map,{[],any,any},unknown}},{{c,atom,[proto_ver],unknown},optional,{c,union,[none,{c,binary,[8,0],unknown},none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown}},{{c,atom,[protocol],unknown},optional,{c,atom,any,unknown}},{{c,atom,[username],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}}],{c,atom,any,unknown},any},unknown},{c,binary,[8,0],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},{c,number,{int_rng,0,255},integer},none,none,none,none],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},none,none,none,none,none],unknown},{c,number,any,integer},any],{10,{c,atom,[message],unknown}}}],{3,{c,atom,[delivery],unknown}}}]},{emqx_conf_proto_v2,update,4} => {any,[{c,atom,any,unknown},{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},any,{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_conf_proto_v1,remove_config,2} => {any,[{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_eviction_agent,all_local_channels_count,0} => {any,[]},{emqx_eviction_agent_proto_v2,all_channels_count,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},any]},{emqx_mgmt_api_trace,read_trace_file,3} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[eof],unknown},{c,union,[{c,atom,[undefined],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown}],{2,{c,atom,[eof],unknown}}},{c,tuple,[{c,atom,[error],unknown},{c,union,[{c,atom,any,unknown},none,none,none,none,none,{c,tuple,[{c,atom,[no_translation],unknown},{c,atom,[unicode],unknown},{c,atom,[latin1],unknown}],{3,{c,atom,[no_translation],unknown}}},none,none,none],unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,binary,[8,0],unknown},any,any]},{emqx_bridge_proto_v1,restart_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_mgmt_api_plugins,get_plugins,0} => {{c,tuple,[{c,atom,any,unknown},{c,list,[{c,map,{[],any,any},unknown},{c,nil,[],unknown}],unknown}],{2,any}},[]},{emqx_retainer_proto_v2,wait_dispatch_complete,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown}]},{emqx_node_rebalance_agent,disable,2} => {any,[any,any]},{emqx_conf_proto_v1,remove_config,3} => {any,[{c,atom,any,unknown},{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_management_proto_v4,kickout_clients,2} => {any,[{c,atom,any,unknown},{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,nil,[],unknown}],unknown}]},{emqx_management_proto_v2,subscribe,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,list,[{c,tuple,[{c,binary,[8,0],unknown},{c,map,{[{{c,atom,[nl],unknown},mandatory,{c,number,{int_set,[0,1]},integer}},{{c,atom,[qos],unknown},mandatory,{c,number,{int_set,[0,1,2]},integer}},{{c,atom,[rap],unknown},mandatory,{c,number,{int_set,[0,1]},integer}},{{c,atom,[rh],unknown},mandatory,{c,number,{int_set,[0,1,2]},integer}},{{c,atom,[share],unknown},optional,{c,binary,[8,0],unknown}}],{c,atom,any,unknown},any},unknown}],{2,any}},{c,nil,[],unknown}],unknown}]},{emqx_bridge_proto_v4,start_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_node_rebalance_api_proto_v1,node_rebalance_evacuation_start,2} => {any,[{c,atom,any,unknown},{c,map,{[{{c,atom,[conn_evict_rate],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[migrate_to],unknown},optional,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}},{{c,atom,[server_reference],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}},{{c,atom,[sess_evict_rate],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[wait_health_check],unknown},optional,{c,number,any,unknown}},{{c,atom,[wait_takeover],unknown},optional,{c,number,any,unknown}}],none,none},unknown}]},{emqx_node_rebalance_evacuation,start,1} => {any,[{c,map,{[],any,any},unknown}]},{emqx_node_rebalance_agent,disable,1} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},{c,atom,[already_disabled,invalid_coordinator],unknown}],{2,{c,atom,[error],unknown}}},none,none,none],unknown},[{c,identifier,[pid],unknown}]},{emqx_mgmt_api_plugins,delete_package,1} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},none,none,none],unknown},[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_delayed_proto_v2,get_delayed_message,2} => {any,[{c,atom,any,unknown},{c,binary,[8,0],unknown}]},{emqx_persistent_session_ds,do_open_iterator,3} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,opaque,[{opaque,emqx_ds_storage_layer,iterator,0,{c,tuple,[{c,atom,[it],unknown},{c,tuple,[{c,atom,any,unknown},{c,binary,[8,0],unknown}],{2,any}},{c,number,{int_rng,0,1114111},integer},{c,tuple,[{c,list,[any,{c,nil,[],unknown}],unknown},{c,number,{int_rng,0,pos_inf},integer}],{2,any}},{c,atom,any,unknown},any],{6,{c,atom,[it],unknown}}}}],unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,list,[{c,union,[{c,atom,['','#','+'],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,nil,[],unknown}],unknown},{c,number,{int_rng,0,pos_inf},integer},{c,binary,[8,0],unknown}]},{emqx_conf_proto_v3,get_config,2} => {any,[{c,atom,any,unknown},{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],unknown}]},{emqx_gateway_cm_proto_v1,get_chann_conn_mod,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_management_proto_v1,broker_info,1} => {any,[{c,atom,any,unknown}]},{emqx_plugins,get_tar,1} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,binary,[8,0],unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},{c,number,{int_rng,0,1114111},integer},none,none,none,none],unknown}]},{emqx_node_rebalance_api_proto_v2,node_rebalance_evacuation_stop,1} => {any,[{c,atom,any,unknown}]},{emqx_delayed_proto_v2,delete_delayed_message,2} => {any,[{c,atom,any,unknown},{c,binary,[8,0],unknown}]},{emqx_metrics,all,0} => {{c,list,[{c,tuple,[any,{c,number,any,integer}],{2,any}},{c,nil,[],unknown}],unknown},[]},{emqx_bridge_proto_v4,get_metrics_from_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_management_proto_v3,call_client,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},any]},{emqx_bridge_proto_v2,restart_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_mgmt_api_configs,get_full_config,0} => {{c,map,{[],any,any},unknown},[]},{emqx_mgmt_api_plugins,install_package,2} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},none,none,none],unknown},[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[none,none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},{c,number,{int_rng,0,1114111},integer},none,none,none,none],unknown},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},{c,number,{int_rng,0,255},integer},none,none,none,none],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_retainer_dispatcher,wait_dispatch_complete,1} => {{c,atom,[ok],unknown},[any]},{emqx_slow_subs_api,get_history,0} => {{c,list,[{c,map,{[{{c,atom,[clientid],unknown},mandatory,any},{{c,atom,[last_update_time],unknown},mandatory,any},{{c,atom,[node],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[timespan],unknown},mandatory,any},{{c,atom,[topic],unknown},mandatory,any}],none,none},unknown},{c,nil,[],unknown}],unknown},[]},{emqx_mgmt_trace_proto_v2,read_trace_file,4} => {any,[{c,atom,any,unknown},{c,binary,[8,0],unknown},{c,number,{int_rng,0,pos_inf},integer},{c,number,{int_rng,0,pos_inf},integer}]},{emqx_node_rebalance,connection_count,0} => {{c,tuple,[{c,atom,[ok],unknown},any],{2,{c,atom,[ok],unknown}}},[]},{emqx_alarm,deactivate,1} => {any,[any]},{emqx_proto_v1,clean_pem_cache,1} => {any,[{c,atom,any,unknown}]},{emqx,reset_config,2} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,map,{[{{c,atom,[config],unknown},optional,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},none,none,none,none,{c,map,{[],{c,atom,any,unknown},any},unknown}],unknown}},{{c,atom,[post_config_update],unknown},optional,{c,map,{[],{c,atom,any,unknown},any},unknown}},{{c,atom,[raw_config],unknown},optional,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},none,none,none,none,{c,map,{[],{c,binary,[8,0],unknown},any},unknown}],unknown}}],none,none},unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},any]},{emqx_conf_proto_v1,reset,2} => {any,[{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_conf_proto_v1,update,4} => {any,[{c,atom,any,unknown},{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},any,{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_conf_proto_v1,get_all,1} => {any,[{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],unknown}]},{emqx_node_rebalance_proto_v1,session_counts,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_node_rebalance_proto_v1,evict_connections,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,number,{int_rng,0,pos_inf},integer}]},{emqx_mgmt_api_plugins_proto_v2,install_package,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,binary,[8,0],unknown}]},{emqx_gateway_cm,do_get_chan_info,3} => {{c,union,[{c,atom,[undefined],unknown},none,none,none,none,none,none,none,none,{c,map,{[{{c,atom,[node],unknown},mandatory,{c,atom,any,unknown}}],any,any},unknown}],unknown},[any,any,any]},{emqx_bridge_proto_v1,restart_bridges_to_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_authz_cache,drain_cache,1} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},{c,atom,[not_found],unknown}],{2,{c,atom,[error],unknown}}},none,none,none],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}]},{emqx_telemetry_proto_v1,get_cluster_uuid,1} => {any,[{c,atom,any,unknown}]},{emqx_node_rebalance_proto_v2,available_nodes,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_cm,do_get_chan_info,2} => {any,[any,any]},{emqx_exhook_mgr,all_servers_info,0} => {any,[]},{emqx,update_config,3} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,map,{[{{c,atom,[config],unknown},optional,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},none,none,none,none,{c,map,{[],{c,atom,any,unknown},any},unknown}],unknown}},{{c,atom,[post_config_update],unknown},optional,{c,map,{[],{c,atom,any,unknown},any},unknown}},{{c,atom,[raw_config],unknown},optional,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},none,none,none,none,{c,map,{[],{c,binary,[8,0],unknown},any},unknown}],unknown}}],none,none},unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},any,{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_node_rebalance,start,1} => {any,[{c,map,{[],any,any},unknown}]},{emqx_mgmt_api_plugins,ensure_action,2} => {{c,atom,[ok],unknown},[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,atom,[restart,start,stop],unknown}]},{emqx_conf_proto_v2,get_config,2} => {any,[{c,atom,any,unknown},{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],unknown}]},{emqx_conf_proto_v3,remove_config,3} => {any,[{c,atom,any,unknown},{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_management_proto_v1,call_client,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},any]},{emqx_node_rebalance_purge_proto_v1,stop,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_bridge_proto_v2,start_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_mgmt,broker_info,0} => {{c,map,{[{{c,atom,[node],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[node_status],unknown},mandatory,{c,atom,[running],unknown}},{{c,atom,[otp_release],unknown},mandatory,{c,binary,[8,0],unknown}}],any,any},unknown},[]},{emqx_delayed,get_delayed_message,1} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,atom,[not_found],unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,map,{[{{c,atom,[delayed_interval],unknown},mandatory,any},{{c,atom,[delayed_remaining],unknown},mandatory,{c,number,any,integer}},{{c,atom,[expected_at],unknown},mandatory,{c,binary,[8,0],unknown}},{{c,atom,[from_clientid],unknown},mandatory,{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}},{{c,atom,[from_username],unknown},mandatory,any},{{c,atom,[msgid],unknown},mandatory,{c,binary,[8,0],unknown}},{{c,atom,[node],unknown},mandatory,any},{{c,atom,[payload],unknown},optional,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},{c,number,{int_rng,0,255},integer},none,none,none,none],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},none,none,none,none,none],unknown}},{{c,atom,[publish_at],unknown},mandatory,{c,binary,[8,0],unknown}},{{c,atom,[qos],unknown},mandatory,any},{{c,atom,[topic],unknown},mandatory,{c,binary,[8,0],unknown}}],none,none},unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},[any]},{emqx_rule_engine,reset_metrics_for_rule,1} => {{c,atom,[ok],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}]},{emqx_proto_v1,is_running,1} => {any,[{c,atom,any,unknown}]},{emqx_bridge_proto_v4,start_bridges_to_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_bridge_proto_v1,lookup_from_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_node_rebalance_proto_v1,disconnected_session_counts,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_management_proto_v3,broker_info,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_cm,do_get_chan_stats,2} => {any,[any,any]},{emqx_node_rebalance_status_proto_v1,evacuation_status,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_gateway_api_listeners_proto_v1,listeners_cluster_status,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,list,[any,{c,nil,[],unknown}],unknown}]},{emqx_license_proto_v2,remote_connection_counts,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_conf_proto_v2,get_config,3} => {any,[{c,atom,any,unknown},{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],unknown},any]},{emqx_bridge_proto_v4,list_bridges_on_nodes,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_cm_proto_v2,takeover_session,2} => {any,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_node_rebalance_purge,stop,0} => {any,[]},{emqx_conf_proto_v3,reset,3} => {any,[{c,atom,any,unknown},{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_persistent_session_ds_proto_v1,close_all_iterators,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,binary,[8,0],unknown}]},{emqx_conf_proto_v2,remove_config,3} => {any,[{c,atom,any,unknown},{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_management_proto_v4,subscribe,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,list,[{c,tuple,[{c,binary,[8,0],unknown},{c,map,{[{{c,atom,[nl],unknown},mandatory,{c,number,{int_set,[0,1]},integer}},{{c,atom,[qos],unknown},mandatory,{c,number,{int_set,[0,1,2]},integer}},{{c,atom,[rap],unknown},mandatory,{c,number,{int_set,[0,1]},integer}},{{c,atom,[rh],unknown},mandatory,{c,number,{int_set,[0,1,2]},integer}},{{c,atom,[share],unknown},optional,{c,binary,[8,0],unknown}}],{c,atom,any,unknown},any},unknown}],{2,any}},{c,nil,[],unknown}],unknown}]},{emqx_gateway_cm,do_call,4} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown},any]},{emqx_ft_storage_exporter_fs_proto_v1,read_export_file,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},none,none,none,{c,list,[{c,union,[{c,atom,any,unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},{c,number,{int_rng,0,1114111},integer},none,none,none,none],unknown},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_dashboard_proto_v1,current_rate,1} => {any,[{c,atom,any,unknown}]},{erlang,send,2} => {any,[any,any]},{emqx_conf_cli,get_config,1} => {{c,union,[none,none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},{c,list,[{c,number,{int_set,"_defknotuy"},integer},{c,nil,[],unknown}],nonempty}],{2,{c,atom,[error],unknown}}},none,none,{c,map,{[],any,any},unknown}],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_node_rebalance_agent,enable,2} => {any,[any,any]},{emqx_gateway_cm,do_kick_session,4} => {{c,atom,[ok],unknown},[{c,atom,any,unknown},any,{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_bridge,list,0} => {any,[]},{emqx_proto_v2,are_running,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_conf_proto_v1,update,3} => {any,[{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},any,{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_conf_proto_v3,update,3} => {any,[{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},any,{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_bridge_proto_v4,stop_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_ft_storage_fs_proxy,lookup_local_assembler,1} => {any,[any]},{emqx_node_rebalance_proto_v2,evict_connections,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,number,{int_rng,0,pos_inf},integer}]},{emqx_persistent_session_ds_proto_v1,open_iterator,4} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,list,[{c,union,[{c,atom,['','#','+'],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,nil,[],unknown}],unknown},{c,number,{int_rng,0,pos_inf},integer},{c,binary,[8,0],unknown}]},{emqx_cm_proto_v2,lookup_client,2} => {any,[{c,atom,any,unknown},{c,tuple_set,[{2,[{c,tuple,[{c,atom,[clientid],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}],{2,{c,atom,[clientid],unknown}}},{c,tuple,[{c,atom,[username],unknown},{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}],{2,{c,atom,[username],unknown}}}]}],unknown}]},{emqx_bridge_proto_v3,stop_bridges_to_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_node_rebalance_agent,enable,1} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},{c,atom,[already_enabled,eviction_agent_busy],unknown}],{2,{c,atom,[error],unknown}}},none,none,none],unknown},[{c,identifier,[pid],unknown}]},{emqx_management_proto_v4,node_info,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_proto_v1,get_stats,1} => {any,[{c,atom,any,unknown}]},{emqx_exhook_mgr,server_info,1} => {any,[any]},{emqx_license_resources,local_connection_count,0} => {any,[]},{emqx_rule_engine_proto_v1,reset_metrics,1} => {any,[{c,binary,[8,0],unknown}]},{emqx_management_proto_v2,node_info,1} => {any,[{c,atom,any,unknown}]},{emqx_gateway_cm_proto_v1,call,5} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown},any,{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown}]},{emqx_bridge_proto_v4,lookup_from_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_cm_proto_v1,get_chan_stats,2} => {any,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_cm,takeover_session,2} => {{c,union,[{c,atom,[none,ok,undefined],unknown},none,none,none,{c,list,[{c,tuple,[{c,atom,any,unknown},any],{2,any}},{c,nil,[],unknown}],unknown},none,{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[expired],unknown},any],{2,{c,atom,[expired],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,union,[none,none,none,none,{c,list,[{c,tuple,[any,any,any],{3,any}},{c,nil,[],unknown}],unknown},none,none,none,none,{c,map,{[],any,any},unknown}],unknown}],{2,{c,atom,[ok],unknown}}},{c,tuple,[{c,atom,[persistent],unknown},any],{2,{c,atom,[persistent],unknown}}}]},{3,[{c,tuple,[{c,atom,[living],unknown},{c,atom,any,unknown},any],{3,{c,atom,[living],unknown}}}]},{4,[{c,tuple,[{c,atom,[living],unknown},{c,atom,any,unknown},{c,identifier,[pid],unknown},any],{4,{c,atom,[living],unknown}}}]}],unknown},none,none,{c,map,{[],{c,atom,any,unknown},any},unknown}],unknown},[any,any]},{emqx_topic_metrics,metrics,1} => {{c,union,[none,none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},{c,atom,[topic_not_found],unknown}],{2,{c,atom,[error],unknown}}},none,none,{c,map,{[{{c,atom,[create_time],unknown},mandatory,any},{{c,atom,[metrics],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[reset_time],unknown},optional,any},{{c,atom,[topic],unknown},mandatory,any}],none,none},unknown}],unknown},[any]},{emqx_node_rebalance_proto_v1,available_nodes,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_exhook_proto_v1,server_hooks_metrics,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},any]},{emqx_mgmt_trace_proto_v2,get_trace_size,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_telemetry,get_cluster_uuid,0} => {any,[]},{emqx_management_proto_v4,get_full_config,1} => {any,[{c,atom,any,unknown}]},{emqx_conf_proto_v3,remove_config,2} => {any,[{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_conf_proto_v3,update,4} => {any,[{c,atom,any,unknown},{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},any,{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_node_rebalance,session_count,0} => {{c,tuple,[{c,atom,[ok],unknown},any],{2,{c,atom,[ok],unknown}}},[]},{emqx_conf_proto_v2,sync_data_from_node,1} => {any,[{c,atom,any,unknown}]},{emqx_proto_v2,delete_all_deactivated_alarms,1} => {any,[{c,atom,any,unknown}]},{emqx_conf_app,sync_data_from_node,0} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,binary,[8,0],unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},[]},{emqx_proto_v1,get_metrics,1} => {any,[{c,atom,any,unknown}]},{emqx_telemetry,get_node_uuid,0} => {any,[]},{emqx_resource,reset_metrics_local,1} => {{c,atom,[ok],unknown},[{c,binary,[8,0],unknown}]},{emqx_mgmt_trace_proto_v2,trace_file,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[{c,atom,any,unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},{c,number,{int_rng,0,1114111},integer},none,none,none,none],unknown},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_bridge_api,get_metrics_from_local_node,2} => {{c,map,{[{{c,atom,[dropped],unknown},mandatory,{c,number,any,integer}},{{c,atom,['dropped.expired'],unknown},mandatory,{c,number,any,integer}},{{c,atom,['dropped.other'],unknown},mandatory,{c,number,any,integer}},{{c,atom,['dropped.queue_full'],unknown},mandatory,{c,number,any,integer}},{{c,atom,['dropped.resource_not_found'],unknown},mandatory,{c,number,any,integer}},{{c,atom,['dropped.resource_stopped'],unknown},mandatory,{c,number,any,integer}},{{c,atom,[failed],unknown},mandatory,{c,number,any,integer}},{{c,atom,[inflight],unknown},mandatory,any},{{c,atom,[late_reply],unknown},mandatory,{c,number,any,integer}},{{c,atom,[matched],unknown},mandatory,{c,number,any,integer}},{{c,atom,[queuing],unknown},mandatory,any},{{c,atom,[rate],unknown},mandatory,any},{{c,atom,[rate_last5m],unknown},mandatory,any},{{c,atom,[rate_max],unknown},mandatory,any},{{c,atom,[received],unknown},mandatory,{c,number,any,integer}},{{c,atom,[retried],unknown},mandatory,{c,number,any,integer}},{{c,atom,[success],unknown},mandatory,{c,number,any,integer}}],none,none},unknown},[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},{c,number,{int_rng,0,255},integer},none,none,none,none],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},{c,number,{int_rng,0,255},integer},none,none,none,none],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_eviction_agent,evict_sessions,3} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},{c,atom,[disabled],unknown}],{2,{c,atom,[error],unknown}}},none,none,none],unknown},[any,{c,union,[{c,atom,any,unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},any]},{emqx_conf_proto_v3,reset,2} => {any,[{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_authz_proto_v1,lookup_from_all_nodes,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,atom,any,unknown}]},{emqx_node_rebalance_proto_v1,connection_counts,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_topic_metrics_proto_v1,reset,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,binary,[8,0],unknown}]},{emqx_resource_proto_v1,reset_metrics,1} => {any,[{c,binary,[8,0],unknown}]},{emqx_gateway_cm_proto_v1,get_chan_stats,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_cm,kick_session,1} => {{c,atom,[ok],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}]},{emqx_management_proto_v3,node_info,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_proto_v1,deactivate_alarm,2} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}]},{emqx_cm_proto_v2,get_chan_stats,2} => {any,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_cm_proto_v1,get_chann_conn_mod,2} => {any,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_node_rebalance_purge_proto_v1,start,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,map,{[{{c,atom,[purge_rate],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}}],none,none},unknown}]},{emqx_management_proto_v2,list_listeners,1} => {any,[{c,atom,any,unknown}]},{emqx_broker,subscriptions_via_topic,1} => {{c,list,[any,{c,nil,[],unknown}],unknown},[any]},{emqx_mgmt,do_kickout_clients,1} => {{c,atom,[ok],unknown},[{c,list,[any,{c,nil,[],unknown}],unknown}]},{emqx_node_rebalance_proto_v1,evict_sessions,4} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,number,{int_rng,0,pos_inf},integer},{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,atom,[connected,connecting,disconnected,idle,reauthenticating],unknown}]},{emqx_gateway_http,gateway_status,1} => {{c,map,{[{{c,atom,[current_connections],unknown},optional,any},{{c,atom,[max_connections],unknown},optional,{c,number,{int_set,[0]},integer}},{{c,atom,[node],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[status],unknown},mandatory,{c,atom,[running,stopped,unloaded],unknown}}],none,none},unknown},[{c,atom,any,unknown}]},{emqx_management_proto_v2,get_full_config,1} => {any,[{c,atom,any,unknown}]},{emqx_management_proto_v2,unsubscribe_batch,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,list,[{c,binary,[8,0],unknown},{c,nil,[],unknown}],unknown}]},{emqx_node_rebalance_proto_v2,connection_counts,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_management_proto_v3,list_subscriptions,1} => {any,[{c,atom,any,unknown}]},{emqx_node_rebalance_proto_v2,evict_sessions,4} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,number,{int_rng,0,pos_inf},integer},{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,atom,[connected,connecting,disconnected,idle,reauthenticating],unknown}]},{emqx_conf_proto_v2,get_override_config_file,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_mgmt_api_plugins,describe_package,1} => {{c,tuple,[{c,atom,any,unknown},{c,list,[{c,map,{[],any,any},unknown},{c,nil,[],unknown}],unknown}],{2,any}},[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_bridge_proto_v3,restart_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_conf_proto_v1,get_config,3} => {any,[{c,atom,any,unknown},{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],unknown},any]},{emqx_alarm,get_alarms,1} => {any,[{c,atom,[activated,all,deactivated],unknown}]},{emqx_cm_proto_v1,kickout_client,2} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}]},{emqx_bridge_api,lookup_from_local_node,2} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,atom,[not_found],unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},any],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_cm,lookup_client,1} => {{c,list,[any,{c,nil,[],unknown}],unknown},[{c,tuple_set,[{2,[{c,tuple,[{c,atom,[clientid],unknown},any],{2,{c,atom,[clientid],unknown}}},{c,tuple,[{c,atom,[username],unknown},any],{2,{c,atom,[username],unknown}}}]}],unknown}]},{emqx_broker,subscriptions,1} => {{c,list,[{c,tuple,[any,any],{2,any}},{c,nil,[],unknown}],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,{c,identifier,[pid],unknown},none,none,none,none,none,none],unknown}]},{emqx_node_rebalance_proto_v2,disconnected_session_counts,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_ft_storage_exporter_fs_proto_v1,list_exports,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,map,{[{{c,atom,[following],unknown},optional,any},{{c,atom,[limit],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[transfer],unknown},optional,{c,tuple,[{c,binary,[8,0],unknown},{c,binary,[8,0],unknown}],{2,any}}}],none,none},unknown}]},{emqx_mgmt_cluster_proto_v2,connected_replicants,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_retainer_mnesia,active_indices,0} => {{c,tuple,[any,any],{2,any}},[]},{emqx_proto_v2,clean_authz_cache,2} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}]},{emqx_proto_v2,deactivate_alarm,2} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}]},{emqx_stats,getstats,0} => {{c,list,[{c,tuple,any,{any,any}},{c,nil,[],unknown}],unknown},[]},{emqx_topic_metrics,metrics,0} => {{c,list,[{c,map,{[{{c,atom,[create_time],unknown},mandatory,any},{{c,atom,[metrics],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[reset_time],unknown},optional,any},{{c,atom,[topic],unknown},mandatory,any}],none,none},unknown},{c,nil,[],unknown}],unknown},[]},{emqx_ft_storage_fs_reader_proto_v1,read,3} => {any,[{c,atom,any,unknown},{c,identifier,[pid],unknown},{c,number,{int_rng,1,pos_inf},integer}]},{emqx_node_rebalance_status,local_status,0} => {{c,union,[{c,atom,[disabled],unknown},none,none,none,none,none,{c,tuple_set,[{2,[{c,tuple,[{c,atom,[evacuation],unknown},any],{2,{c,atom,[evacuation],unknown}}},{c,tuple,[{c,atom,[purge],unknown},any],{2,{c,atom,[purge],unknown}}},{c,tuple,[{c,atom,[rebalance],unknown},{c,map,{[],{c,atom,[connection_eviction_rate,connection_goal,coordinator_node,disconnected_session_goal,recipients,session_eviction_rate,state,stats],unknown},any},unknown}],{2,{c,atom,[rebalance],unknown}}}]}],unknown},none,none,none],unknown},[]},{emqx_authz_cache,drain_cache,0} => {{c,atom,[ok],unknown},[]},{emqx_node_rebalance_status,evacuation_status,0} => {{c,tuple,[{c,atom,any,unknown},{c,union,[{c,atom,[disabled],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[enabled],unknown},{c,map,{[{{c,atom,[conn_evict_rate],unknown},mandatory,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[current_conns],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[current_sessions],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[initial_conns],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[initial_sessions],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[migrate_to],unknown},mandatory,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}},{{c,atom,[server_reference],unknown},mandatory,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}},{{c,atom,[sess_evict_rate],unknown},mandatory,{c,number,{int_rng,1,pos_inf},integer}}],none,none},unknown}],{2,{c,atom,[enabled],unknown}}},none,none,none],unknown}],{2,any}},[]},{emqx_resource,remove_local,1} => {{c,atom,[ok],unknown},[{c,binary,[8,0],unknown}]},{emqx_mgmt_cluster_proto_v1,invite_node,2} => {any,[{c,atom,any,unknown},{c,atom,any,unknown}]},{emqx_mgmt,do_list_subscriptions,0} => {none,[]},{emqx_delayed_proto_v1,delete_delayed_message,2} => {any,[{c,atom,any,unknown},{c,binary,[8,0],unknown}]},{emqx_management_proto_v2,call_client,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},any]},{emqx_conf_proto_v2,get_all,1} => {any,[{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],unknown}]},{emqx_management_proto_v4,unsubscribe_batch,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,list,[{c,binary,[8,0],unknown},{c,nil,[],unknown}],unknown}]},{emqx_authz_api_sources,lookup_from_local_node,1} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,tuple,[{c,atom,any,unknown},{c,union,[{c,atom,[not_found_resource],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}],{2,any}}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,tuple,[{c,atom,any,unknown},{c,atom,[connected,connecting,disconnected,stopped],unknown},{c,map,{[{{c,atom,[counters],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[gauges],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[rate],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[slides],unknown},mandatory,{c,map,{[],any,any},unknown}}],none,none},unknown},{c,map,{[{{c,atom,[counters],unknown},optional,{c,map,{[],any,any},unknown}},{{c,atom,[gauges],unknown},optional,{c,map,{[],any,any},unknown}},{{c,atom,[rate],unknown},optional,{c,map,{[],any,any},unknown}},{{c,atom,[slides],unknown},optional,{c,map,{[],any,any},unknown}}],none,none},unknown}],{4,any}}],{2,{c,atom,[ok],unknown}}}]}],unknown},[any]},{emqx_node_rebalance_status_proto_v2,evacuation_status,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_node_rebalance_evacuation_proto_v1,available_nodes,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_cm_proto_v1,lookup_client,2} => {any,[{c,atom,any,unknown},{c,tuple_set,[{2,[{c,tuple,[{c,atom,[clientid],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}],{2,{c,atom,[clientid],unknown}}},{c,tuple,[{c,atom,[username],unknown},{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}],{2,{c,atom,[username],unknown}}}]}],unknown}]},{emqx_management_proto_v4,list_listeners,1} => {any,[{c,atom,any,unknown}]},{emqx,remove_config,2} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,map,{[{{c,atom,[config],unknown},optional,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},none,none,none,none,{c,map,{[],{c,atom,any,unknown},any},unknown}],unknown}},{{c,atom,[post_config_update],unknown},optional,{c,map,{[],{c,atom,any,unknown},any},unknown}},{{c,atom,[raw_config],unknown},optional,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},none,none,none,none,{c,map,{[],{c,binary,[8,0],unknown},any},unknown}],unknown}}],none,none},unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_management_proto_v1,list_listeners,1} => {any,[{c,atom,any,unknown}]},{emqx_resource_proto_v1,remove,1} => {any,[{c,binary,[8,0],unknown}]},{emqx_node_rebalance_proto_v2,enable_rebalance_agent,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,identifier,[pid],unknown}]},{emqx_shared_sub_proto_v1,send,4} => {any,[{c,atom,any,unknown},{c,identifier,[pid],unknown},{c,binary,[8,0],unknown},any]},{emqx_cm_proto_v2,takeover_finish,2} => {any,[{c,atom,any,unknown},{c,identifier,[pid],unknown}]},{emqx_broker_proto_v1,list_client_subscriptions,2} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}]},{emqx_authn_api,lookup_from_local_node,2} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,tuple,[{c,atom,any,unknown},{c,union,[{c,atom,[not_found_resource],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}],{2,any}}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,tuple,[{c,atom,any,unknown},{c,atom,[connected,connecting,disconnected,stopped],unknown},{c,map,{[{{c,atom,[counters],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[gauges],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[rate],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[slides],unknown},mandatory,{c,map,{[],any,any},unknown}}],none,none},unknown},{c,map,{[{{c,atom,[counters],unknown},optional,{c,map,{[],any,any},unknown}},{{c,atom,[gauges],unknown},optional,{c,map,{[],any,any},unknown}},{{c,atom,[rate],unknown},optional,{c,map,{[],any,any},unknown}},{{c,atom,[slides],unknown},optional,{c,map,{[],any,any},unknown}}],none,none},unknown}],{4,any}}],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,atom,any,unknown},{c,binary,[8,0],unknown}]},{emqx_eviction_agent,evict_connections,1} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},{c,atom,[disabled],unknown}],{2,{c,atom,[error],unknown}}},none,none,none],unknown},[any]},{emqx_management_proto_v1,get_full_config,1} => {any,[{c,atom,any,unknown}]},{emqx_mgmt_api_cluster,join,1} => {any,[any]},{emqx_node_rebalance,disconnected_session_count,0} => {{c,tuple,[{c,atom,[ok],unknown},any],{2,{c,atom,[ok],unknown}}},[]},{emqx_proto_v1,clean_authz_cache,1} => {any,[{c,atom,any,unknown}]},{emqx_conf,get_node_and_config,1} => {{c,tuple,[{c,atom,any,unknown},any],{2,any}},[{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],unknown}]},{emqx_node_rebalance_status_proto_v1,rebalance_status,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_gateway_cm,do_takeover_session,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_ft_storage_fs_proto_v1,list_assemblers,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,tuple,[{c,binary,[8,0],unknown},{c,binary,[8,0],unknown}],{2,any}}]},{emqx_dashboard_monitor,do_sample,2} => {any,[{c,atom,any,unknown},any]},{emqx_persistent_session_ds,do_ensure_iterator_closed,1} => {{c,atom,[ok],unknown},[{c,binary,[8,0],unknown}]},{emqx_node_rebalance_status,rebalance_status,0} => {{c,tuple,[{c,atom,any,unknown},{c,union,[{c,atom,[disabled],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[enabled],unknown},{c,map,{[],any,any},unknown}],{2,{c,atom,[enabled],unknown}}},none,none,none],unknown}],{2,any}},[]},{emqx_mgmt_api_plugins_proto_v1,delete_package,1} => {any,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_gateway_cm,do_call,5} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown},any,any]},{emqx_mgmt_trace_proto_v1,read_trace_file,4} => {any,[{c,atom,any,unknown},{c,binary,[8,0],unknown},{c,number,{int_rng,0,pos_inf},integer},{c,number,{int_rng,0,pos_inf},integer}]},{emqx_plugins_proto_v1,get_tar,3} => {any,[{c,atom,any,unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown}]},{emqx_authn_proto_v1,lookup_from_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,atom,any,unknown},{c,binary,[8,0],unknown}]},{emqx_ft_storage_fs_proxy,list_local,2} => {any,[any,any]},{emqx_management_proto_v1,node_info,1} => {any,[{c,atom,any,unknown}]},{emqx_ft_storage_fs_proxy,pread_local,4} => {any,[any,any,any,any]},{emqx_resource_proto_v1,create_dry_run,2} => {any,[{c,atom,any,unknown},any]},{emqx_management_proto_v1,unsubscribe,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,binary,[8,0],unknown}]},{emqx_proto_v1,get_alarms,2} => {any,[{c,atom,any,unknown},{c,atom,[activated,all,deactivated],unknown}]},{emqx_ft_storage_fs_proto_v1,pread,5} => {any,[{c,atom,any,unknown},{c,tuple,[{c,binary,[8,0],unknown},{c,binary,[8,0],unknown}],{2,any}},{c,map,{[{{c,atom,[fragment],unknown},mandatory,{c,tuple_set,[{2,[{c,tuple,[{c,atom,[filemeta],unknown},{c,map,{[{{c,atom,[checksum],unknown},optional,{c,tuple,[{c,atom,any,unknown},{c,binary,[8,0],unknown}],{2,any}}},{{c,atom,[expire_at],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[name],unknown},mandatory,{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown}},{{c,atom,[segments_ttl],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[size],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[user_data],unknown},optional,{c,union,[{c,atom,[false,null,true],unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[{c,atom,[false,null,true],unknown},{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,nil,[],unknown}],unknown},{c,number,any,unknown},none,none,none,{c,map,{[],{c,binary,[8,0],unknown},any},unknown}],unknown},{c,nil,[],unknown}],unknown},{c,number,any,unknown},none,none,none,{c,map,{[],{c,binary,[8,0],unknown},{c,union,[{c,atom,[false,null,true],unknown},{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,nil,[],unknown}],unknown},{c,number,any,unknown},none,none,none,{c,map,{[],{c,binary,[8,0],unknown},any},unknown}],unknown}},unknown}],unknown}}],none,none},unknown}],{2,{c,atom,[filemeta],unknown}}},{c,tuple,[{c,atom,[segment],unknown},{c,map,{[{{c,atom,[offset],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[size],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}}],none,none},unknown}],{2,{c,atom,[segment],unknown}}}]}],unknown}},{{c,atom,[path],unknown},mandatory,{c,union,[{c,atom,any,unknown},none,none,none,{c,list,[{c,union,[{c,atom,any,unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},{c,number,{int_rng,0,1114111},integer},none,none,none,none],unknown},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}},{{c,atom,[size],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[timestamp],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}}],none,none},unknown},{c,number,{int_rng,0,pos_inf},integer},{c,number,{int_rng,0,pos_inf},integer}]},{emqx_topic_metrics,reset,0} => {any,[]},{emqx_resource_proto_v1,create,5} => {any,[{c,binary,[8,0],unknown},{c,binary,[8,0],unknown},{c,atom,any,unknown},any,{c,map,{[{{c,atom,[auto_restart_interval],unknown},optional,{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,1,pos_inf},integer},none,none,none,none],unknown}},{{c,atom,[auto_retry_interval],unknown},optional,{c,number,any,integer}},{{c,atom,[batch_size],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[batch_time],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[health_check_interval],unknown},optional,{c,number,any,integer}},{{c,atom,[health_check_timeout],unknown},optional,{c,number,any,integer}},{{c,atom,[inflight_window],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[max_buffer_bytes],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[query_mode],unknown},optional,{c,atom,[async,no_queries,simple_async,simple_sync,sync],unknown}},{{c,atom,[resume_interval],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[start_after_created],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[start_timeout],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[wait_for_resource_ready],unknown},optional,{c,number,any,integer}},{{c,atom,[worker_pool_size],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}}],none,none},unknown}]},{emqx_bridge_proto_v4,restart_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_management_proto_v2,unsubscribe,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,binary,[8,0],unknown}]},{emqx_prometheus,do_stop,0} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},{c,atom,[not_found,restarting,running,simple_one_for_one],unknown}],{2,{c,atom,[error],unknown}}},none,none,none],unknown},[]},{emqx_conf_proto_v1,get_override_config_file,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_bridge_proto_v1,stop_bridges_to_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_prometheus,do_start,0} => {{c,atom,[ok],unknown},[]},{emqx_cm_proto_v1,get_chan_info,2} => {any,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_mgmt_trace_proto_v1,trace_file,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[{c,atom,any,unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},{c,number,{int_rng,0,1114111},integer},none,none,none,none],unknown},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_node_rebalance_api_proto_v1,node_rebalance_start,2} => {any,[{c,atom,any,unknown},{c,map,{[{{c,atom,[abs_conn_threshold],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[abs_sess_threshold],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[conn_evict_rate],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[nodes],unknown},optional,{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}},{{c,atom,[rel_conn_threshold],unknown},optional,{c,number,any,unknown}},{{c,atom,[rel_sess_threshold],unknown},optional,{c,number,any,unknown}},{{c,atom,[sess_evict_rate],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[wait_health_check],unknown},optional,{c,number,any,unknown}},{{c,atom,[wait_takeover],unknown},optional,{c,number,any,unknown}}],none,none},unknown}]},{emqx_conf_proto_v3,get_override_config_file,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_management_proto_v3,unsubscribe_batch,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,list,[{c,binary,[8,0],unknown},{c,nil,[],unknown}],unknown}]},{emqx_exhook_proto_v1,all_servers_info,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_eviction_agent,purge_sessions,1} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},{c,atom,[disabled],unknown}],{2,{c,atom,[error],unknown}}},none,none,none],unknown},[any]},{emqx_management_proto_v3,unsubscribe,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,binary,[8,0],unknown}]},{emqx_proto_v1,clean_authz_cache,2} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}]},{emqx_mgmt,do_subscribe,2} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,atom,[channel_not_found],unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[subscribe],unknown},any],{2,{c,atom,[subscribe],unknown}}}]}],unknown},[any,any]},{emqx_mgmt_api_trace,get_trace_size,0} => {{c,map,{[],any,any},unknown},[]},{emqx_alarm,delete_all_deactivated_alarms,0} => {any,[]},{emqx_cm,takeover_finish,2} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,atom,[noproc,timeout,unexpected_exception],unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},any],{2,{c,atom,[ok],unknown}}}]}],unknown},none,none,none],unknown},[{c,atom,any,unknown},{c,identifier,[pid],unknown}]},{emqx_management_proto_v3,subscribe,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,list,[{c,tuple,[{c,binary,[8,0],unknown},{c,map,{[{{c,atom,[nl],unknown},mandatory,{c,number,{int_set,[0,1]},integer}},{{c,atom,[qos],unknown},mandatory,{c,number,{int_set,[0,1,2]},integer}},{{c,atom,[rap],unknown},mandatory,{c,number,{int_set,[0,1]},integer}},{{c,atom,[rh],unknown},mandatory,{c,number,{int_set,[0,1,2]},integer}},{{c,atom,[share],unknown},optional,{c,binary,[8,0],unknown}}],{c,atom,any,unknown},any},unknown}],{2,any}},{c,nil,[],unknown}],unknown}]},{emqx_mgmt_api_plugins_proto_v1,get_plugins,0} => {any,[]},{emqx_metrics_proto_v1,get_metrics,4} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown}]},{emqx_mgmt_cluster_proto_v2,invite_node,2} => {any,[{c,atom,any,unknown},{c,atom,any,unknown}]},{emqx_shared_sub_proto_v1,dispatch_with_ack,5} => {any,[{c,identifier,[pid],unknown},{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,binary,[8,0],unknown},{c,tuple,[{c,atom,[message],unknown},{c,binary,[8,0],unknown},any,{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,map,{[],{c,atom,any,unknown},{c,atom,[false,true],unknown}},unknown},{c,map,{[{{c,atom,[allow_publish],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[peerhost],unknown},optional,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown}},{{c,atom,[properties],unknown},optional,{c,map,{[],{c,atom,any,unknown},any},unknown}},{{c,atom,[proto_ver],unknown},optional,{c,union,[none,{c,binary,[8,0],unknown},none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown}},{{c,atom,[protocol],unknown},optional,{c,atom,any,unknown}},{{c,atom,[username],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}}],{c,atom,any,unknown},any},unknown},{c,binary,[8,0],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},{c,number,{int_rng,0,255},integer},none,none,none,none],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},none,none,none,none,none],unknown},{c,number,any,integer},any],{10,{c,atom,[message],unknown}}},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown}]},{emqx_node_rebalance,stop,0} => {any,[]},{emqx_gateway_cm_proto_v1,set_chan_stats,4} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown},{c,list,[{c,tuple,[{c,atom,any,unknown},any],{2,any}},{c,nil,[],unknown}],unknown}]},{emqx_ft_storage_exporter_fs_proxy,read_export_file_local,2} => {any,[any,any]},{emqx_slow_subs_proto_v1,clear_history,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_bridge_proto_v3,start_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_bridge_proto_v4,restart_bridges_to_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_gateway_cm,do_set_chan_info,4} => {{c,atom,[false,true],unknown},[any,any,any,any]},{emqx_bridge_proto_v3,list_bridges,1} => {any,[{c,atom,any,unknown}]},{emqx_node_rebalance_proto_v2,enable_rebalance_agent,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,identifier,[pid],unknown},any]},{emqx_resource,create_local,5} => {{c,tuple,[{c,atom,[ok],unknown},{c,map,{[{{c,atom,[callback_mode],unknown},mandatory,{c,atom,[always_sync,async_if_possible],unknown}},{{c,atom,[config],unknown},mandatory,any},{{c,atom,[error],unknown},mandatory,any},{{c,atom,[id],unknown},mandatory,{c,binary,[8,0],unknown}},{{c,atom,[mod],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[query_mode],unknown},mandatory,{c,atom,[async,no_queries,simple_async,simple_sync,sync],unknown}},{{c,atom,[state],unknown},mandatory,any},{{c,atom,[status],unknown},mandatory,{c,atom,[connected,connecting,disconnected,stopped],unknown}}],none,none},unknown}],{2,{c,atom,[ok],unknown}}},[{c,binary,[8,0],unknown},{c,binary,[8,0],unknown},{c,atom,any,unknown},any,{c,map,{[{{c,atom,[auto_restart_interval],unknown},optional,{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,1,pos_inf},integer},none,none,none,none],unknown}},{{c,atom,[auto_retry_interval],unknown},optional,{c,number,any,integer}},{{c,atom,[batch_size],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[batch_time],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[health_check_interval],unknown},optional,{c,number,any,integer}},{{c,atom,[health_check_timeout],unknown},optional,{c,number,any,integer}},{{c,atom,[inflight_window],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[max_buffer_bytes],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[query_mode],unknown},optional,{c,atom,[async,no_queries,simple_async,simple_sync,sync],unknown}},{{c,atom,[resume_interval],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[start_after_created],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[start_timeout],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[wait_for_resource_ready],unknown},optional,{c,number,any,integer}},{{c,atom,[worker_pool_size],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}}],none,none},unknown}]},{emqx_gateway_cm_proto_v1,takeover_session,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_resource_proto_v1,recreate,4} => {any,[{c,binary,[8,0],unknown},{c,atom,any,unknown},any,{c,map,{[{{c,atom,[auto_restart_interval],unknown},optional,{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,1,pos_inf},integer},none,none,none,none],unknown}},{{c,atom,[auto_retry_interval],unknown},optional,{c,number,any,integer}},{{c,atom,[batch_size],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[batch_time],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[health_check_interval],unknown},optional,{c,number,any,integer}},{{c,atom,[health_check_timeout],unknown},optional,{c,number,any,integer}},{{c,atom,[inflight_window],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[max_buffer_bytes],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[query_mode],unknown},optional,{c,atom,[async,no_queries,simple_async,simple_sync,sync],unknown}},{{c,atom,[resume_interval],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[start_after_created],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[start_timeout],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[wait_for_resource_ready],unknown},optional,{c,number,any,integer}},{{c,atom,[worker_pool_size],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}}],none,none},unknown}]},{emqx_bridge_proto_v3,list_bridges_on_nodes,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_exhook_proto_v1,server_info,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},any]},{emqx_bridge_proto_v2,stop_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_slow_subs_proto_v1,get_history,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_mgmt_api_plugins_proto_v2,describe_package,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx,is_running,0} => {{c,atom,[false,true],unknown},[]},{emqx_cm_proto_v2,get_chann_conn_mod,2} => {any,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_resource,recreate_local,4} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,atom,[not_found,updating_to_incorrect_resource_type],unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,map,{[{{c,atom,[callback_mode],unknown},mandatory,{c,atom,[always_sync,async_if_possible],unknown}},{{c,atom,[config],unknown},mandatory,any},{{c,atom,[error],unknown},mandatory,any},{{c,atom,[id],unknown},mandatory,{c,binary,[8,0],unknown}},{{c,atom,[mod],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[query_mode],unknown},mandatory,{c,atom,[async,no_queries,simple_async,simple_sync,sync],unknown}},{{c,atom,[state],unknown},mandatory,any},{{c,atom,[status],unknown},mandatory,{c,atom,[connected,connecting,disconnected,stopped],unknown}}],none,none},unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,binary,[8,0],unknown},{c,atom,any,unknown},any,{c,map,{[{{c,atom,[auto_restart_interval],unknown},optional,{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,1,pos_inf},integer},none,none,none,none],unknown}},{{c,atom,[auto_retry_interval],unknown},optional,{c,number,any,integer}},{{c,atom,[batch_size],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[batch_time],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[health_check_interval],unknown},optional,{c,number,any,integer}},{{c,atom,[health_check_timeout],unknown},optional,{c,number,any,integer}},{{c,atom,[inflight_window],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[max_buffer_bytes],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[query_mode],unknown},optional,{c,atom,[async,no_queries,simple_async,simple_sync,sync],unknown}},{{c,atom,[resume_interval],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[start_after_created],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[start_timeout],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[wait_for_resource_ready],unknown},optional,{c,number,any,integer}},{{c,atom,[worker_pool_size],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}}],none,none},unknown}]},{emqx_bridge_resource,stop,2} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},none,none,none],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},{c,number,{int_rng,0,255},integer},none,none,none,none],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},{c,number,{int_rng,0,255},integer},none,none,none,none],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_bridge_proto_v1,list_bridges,1} => {any,[{c,atom,any,unknown}]},{emqx_bridge_resource,start,2} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},none,none,none],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},{c,number,{int_rng,0,255},integer},none,none,none,none],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},{c,number,{int_rng,0,255},integer},none,none,none,none],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_mgmt_api_plugins_proto_v2,delete_package,1} => {any,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_node_rebalance_evacuation,stop,0} => {any,[]},{ssl_pem_cache,clear,0} => {any,[]},{emqx_node_rebalance_evacuation,is_node_available,0} => {{c,atom,any,unknown},[]},{emqx_conf_proto_v3,get_config,3} => {any,[{c,atom,any,unknown},{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],unknown},any]},{emqx_conf_proto_v3,get_hocon_config,2} => {any,[{c,atom,any,unknown},{c,binary,[8,0],unknown}]},{emqx_topic_metrics,reset,1} => {any,[any]},{emqx_gateway_cm,do_cast,4} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown},any]},{emqx_ft_storage_fs_proto_v1,multilist,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,tuple,[{c,binary,[8,0],unknown},{c,binary,[8,0],unknown}],{2,any}},{c,atom,[fragment,result],unknown}]},{emqx_bridge_proto_v3,stop_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_node_rebalance_api_proto_v2,node_rebalance_purge_stop,1} => {any,[{c,atom,any,unknown}]},{emqx_metrics_worker,get_metrics,2} => {{c,map,{[{{c,atom,[counters],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[gauges],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[rate],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[slides],unknown},mandatory,{c,map,{[],any,any},unknown}}],none,none},unknown},[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}]},{emqx_management_proto_v4,list_subscriptions,1} => {any,[{c,atom,any,unknown}]},{emqx_cm_proto_v2,kickout_client,2} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}]},{emqx_cm_proto_v1,takeover_session,2} => {any,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_gateway_http_proto_v1,get_cluster_status,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,atom,any,unknown}]},{emqx_gateway_api_listeners,do_listeners_cluster_status,1} => {{c,map,{[],any,any},unknown},[{c,list,[any,{c,nil,[],unknown}],unknown}]},{emqx_node_rebalance_purge,start,1} => {any,[{c,map,{[],any,any},unknown}]},{emqx_mgmt,do_unsubscribe_batch,2} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,atom,[channel_not_found],unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[unsubscribe],unknown},{c,list,[{c,tuple,[any,any],{2,any}},{c,nil,[],unknown}],unknown}],{2,{c,atom,[unsubscribe],unknown}}}]}],unknown},[any,any]},{emqx_node_rebalance_proto_v2,disable_rebalance_agent,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,identifier,[pid],unknown},any]},{emqx_gateway_cm_proto_v1,get_chan_info,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_shared_sub,do_dispatch_with_ack,4} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},none,none,none],unknown},[{c,identifier,[pid,port],unknown},any,any,{c,tuple,[{c,atom,[message],unknown},{c,binary,[8,0],unknown},any,{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,map,{[],{c,atom,any,unknown},{c,atom,[false,true],unknown}},unknown},{c,map,{[{{c,atom,[allow_publish],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[peerhost],unknown},optional,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown}},{{c,atom,[properties],unknown},optional,{c,map,{[],{c,atom,any,unknown},any},unknown}},{{c,atom,[proto_ver],unknown},optional,{c,union,[none,{c,binary,[8,0],unknown},none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown}},{{c,atom,[protocol],unknown},optional,{c,atom,any,unknown}},{{c,atom,[username],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}}],{c,atom,any,unknown},any},unknown},{c,binary,[8,0],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},{c,number,{int_rng,0,255},integer},none,none,none,none],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},none,none,none,none,none],unknown},{c,number,any,integer},any],{10,{c,atom,[message],unknown}}}]},{emqx_mgmt,do_unsubscribe,2} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,atom,[channel_not_found],unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[unsubscribe],unknown},{c,list,[{c,tuple,[{c,binary,[8,0],unknown},{c,map,{[],any,any},unknown}],{2,any}},{c,nil,[],unknown}],nonempty}],{2,{c,atom,[unsubscribe],unknown}}}]}],unknown},[any,any]},{emqx_eviction_agent,evict_session_channel,3} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,union,[{c,atom,[undefined],unknown},none,none,{c,identifier,[pid],unknown},none,none,none,none,none,none],unknown}],{2,{c,atom,[ok],unknown}}}]},{3,[{c,tuple,[{c,atom,[ok],unknown},{c,union,[{c,atom,[undefined],unknown},none,none,{c,identifier,[pid],unknown},none,none,none,none,none,none],unknown},any],{3,{c,atom,[ok],unknown}}}]}],unknown},[any,{c,map,{[{{c,atom,[clean_start],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[clientid],unknown},optional,{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}},{{c,atom,[conn_mod],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[conn_props],unknown},optional,{c,map,{[],{c,atom,any,unknown},any},unknown}},{{c,atom,[connected],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[connected_at],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[disconnected_at],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[expiry_interval],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[keepalive],unknown},optional,{c,number,{int_rng,0,1114111},integer}},{{c,atom,[peercert],unknown},optional,{c,union,[{c,atom,[nossl,undefined],unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[{c,atom,any,unknown},none,none,none,none,none,{c,tuple,any,{any,any}},none,none,none],unknown},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}},{{c,atom,[peername],unknown},mandatory,{c,tuple,[{c,union,[{c,atom,[local,undefined,unspec],unknown},none,none,none,none,none,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown},none,none,none],unknown},any],{2,any}}},{{c,atom,[proto_name],unknown},optional,{c,binary,[8,0],unknown}},{{c,atom,[proto_ver],unknown},optional,{c,union,[none,{c,binary,[8,0],unknown},none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown}},{{c,atom,[receive_maximum],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[sockname],unknown},mandatory,{c,tuple,[{c,union,[{c,atom,[local,undefined,unspec],unknown},none,none,none,none,none,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown},none,none,none],unknown},any],{2,any}}},{{c,atom,[socktype],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[username],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}}],{c,atom,any,unknown},any},unknown},{c,map,{[{{c,atom,[anonymous],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[auth_result],unknown},optional,{c,atom,[bad_authentication_method,bad_clientid_or_password,bad_username_or_password,banned,client_identifier_not_valid,not_authorized,server_busy,server_unavailable,success],unknown}},{{c,atom,[clientid],unknown},mandatory,{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}},{{c,atom,[cn],unknown},optional,{c,binary,[8,0],unknown}},{{c,atom,[dn],unknown},optional,{c,binary,[8,0],unknown}},{{c,atom,[is_bridge],unknown},mandatory,{c,atom,[false,true],unknown}},{{c,atom,[is_superuser],unknown},mandatory,{c,atom,[false,true],unknown}},{{c,atom,[mountpoint],unknown},mandatory,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}},{{c,atom,[password],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}},{{c,atom,[peerhost],unknown},mandatory,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown}},{{c,atom,[protocol],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[sockport],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[username],unknown},mandatory,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}},{{c,atom,[ws_cookie],unknown},optional,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}},{{c,atom,[zone],unknown},mandatory,{c,atom,any,unknown}}],{c,atom,any,unknown},any},unknown}]},{emqx_node_rebalance_status_proto_v1,local_status,1} => {any,[{c,atom,any,unknown}]},{emqx_bridge_proto_v2,list_bridges,1} => {any,[{c,atom,any,unknown}]},{emqx_cm,do_kick_session,3} => {{c,atom,[ok],unknown},[any,{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_gateway_cm,do_get_chan_stats,3} => {any,[any,any,any]},{emqx_delayed_proto_v1,get_delayed_message,2} => {any,[{c,atom,any,unknown},{c,binary,[8,0],unknown}]},{emqx_node_rebalance_status_proto_v2,rebalance_status,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_management_proto_v4,broker_info,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_delayed_proto_v2,clear_all,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_proto_v2,get_alarms,2} => {any,[{c,atom,any,unknown},{c,atom,[activated,all,deactivated],unknown}]},{emqx_mgmt,do_call_client,2} => {any,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},any]},{emqx_slow_subs,clear_history,0} => {any,[]},{emqx_gateway_cm_proto_v1,cast,4} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown},any]},{emqx_conf_proto_v1,reset,3} => {any,[{c,atom,any,unknown},{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_mgmt_trace_proto_v1,get_trace_size,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_gateway_cm_proto_v1,lookup_by_clientid,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}]},{emqx_management_proto_v1,subscribe,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,list,[{c,tuple,[{c,binary,[8,0],unknown},{c,map,{[{{c,atom,[nl],unknown},mandatory,{c,number,{int_set,[0,1]},integer}},{{c,atom,[qos],unknown},mandatory,{c,number,{int_set,[0,1,2]},integer}},{{c,atom,[rap],unknown},mandatory,{c,number,{int_set,[0,1]},integer}},{{c,atom,[rh],unknown},mandatory,{c,number,{int_set,[0,1,2]},integer}},{{c,atom,[share],unknown},optional,{c,binary,[8,0],unknown}}],{c,atom,any,unknown},any},unknown}],{2,any}},{c,nil,[],unknown}],unknown}]},{emqx_telemetry_proto_v1,get_node_uuid,1} => {any,[{c,atom,any,unknown}]},{emqx_conf_proto_v2,remove_config,2} => {any,[{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_mgmt,node_info,0} => {{c,map,{[{{c,atom,[connections],unknown},mandatory,any},{{c,atom,[edition],unknown},mandatory,{c,binary,[0,80],unknown}},{{c,atom,[live_connections],unknown},mandatory,any},{{c,atom,[load1],unknown},optional,{c,number,any,float}},{{c,atom,[load15],unknown},optional,{c,number,any,float}},{{c,atom,[load5],unknown},optional,{c,number,any,float}},{{c,atom,[log_path],unknown},mandatory,{c,binary,[8,0],unknown}},{{c,atom,[max_fds],unknown},mandatory,any},{{c,atom,[memory_total],unknown},mandatory,{c,number,any,unknown}},{{c,atom,[memory_used],unknown},mandatory,{c,number,any,integer}},{{c,atom,[node],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[node_status],unknown},mandatory,{c,atom,[running],unknown}},{{c,atom,[otp_release],unknown},mandatory,{c,binary,[8,0],unknown}},{{c,atom,[process_available],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[process_used],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[role],unknown},mandatory,{c,atom,[core,replicant],unknown}},{{c,atom,[sys_path],unknown},mandatory,{c,binary,[8,0],unknown}},{{c,atom,[uptime],unknown},mandatory,any},{{c,atom,[version],unknown},mandatory,{c,binary,[8,0],unknown}}],none,none},unknown},[]},{emqx_mgmt_api_plugins_proto_v2,ensure_action,2} => {any,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,atom,[restart,start,stop],unknown}]},{emqx_bridge_proto_v3,start_bridges_to_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_node_rebalance_status,purge_status,0} => {{c,tuple,[{c,atom,any,unknown},{c,union,[{c,atom,[disabled],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[enabled],unknown},{c,map,{[{{c,atom,[current_sessions],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[initial_sessions],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[purge_rate],unknown},mandatory,{c,number,{int_rng,1,pos_inf},integer}}],none,none},unknown}],{2,{c,atom,[enabled],unknown}}},none,none,none],unknown}],{2,any}},[]},{emqx_proto_v1,delete_all_deactivated_alarms,1} => {any,[{c,atom,any,unknown}]},{emqx_cm_proto_v2,get_chan_info,2} => {any,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_eviction_agent_proto_v1,evict_session_channel,4} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,map,{[{{c,atom,[clean_start],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[clientid],unknown},optional,{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}},{{c,atom,[conn_mod],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[conn_props],unknown},optional,{c,map,{[],{c,atom,any,unknown},any},unknown}},{{c,atom,[connected],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[connected_at],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[disconnected_at],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[expiry_interval],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[keepalive],unknown},optional,{c,number,{int_rng,0,1114111},integer}},{{c,atom,[peercert],unknown},optional,{c,union,[{c,atom,[nossl,undefined],unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[{c,atom,any,unknown},none,none,none,none,none,{c,tuple,any,{any,any}},none,none,none],unknown},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}},{{c,atom,[peername],unknown},mandatory,{c,tuple,[{c,union,[{c,atom,[local,undefined,unspec],unknown},none,none,none,none,none,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown},none,none,none],unknown},any],{2,any}}},{{c,atom,[proto_name],unknown},optional,{c,binary,[8,0],unknown}},{{c,atom,[proto_ver],unknown},optional,{c,union,[none,{c,binary,[8,0],unknown},none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown}},{{c,atom,[receive_maximum],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[sockname],unknown},mandatory,{c,tuple,[{c,union,[{c,atom,[local,undefined,unspec],unknown},none,none,none,none,none,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown},none,none,none],unknown},any],{2,any}}},{{c,atom,[socktype],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[username],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}}],{c,atom,any,unknown},any},unknown},{c,map,{[{{c,atom,[anonymous],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[auth_result],unknown},optional,{c,atom,[bad_authentication_method,bad_clientid_or_password,bad_username_or_password,banned,client_identifier_not_valid,not_authorized,server_busy,server_unavailable,success],unknown}},{{c,atom,[clientid],unknown},mandatory,{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}},{{c,atom,[cn],unknown},optional,{c,binary,[8,0],unknown}},{{c,atom,[dn],unknown},optional,{c,binary,[8,0],unknown}},{{c,atom,[is_bridge],unknown},mandatory,{c,atom,[false,true],unknown}},{{c,atom,[is_superuser],unknown},mandatory,{c,atom,[false,true],unknown}},{{c,atom,[mountpoint],unknown},mandatory,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}},{{c,atom,[password],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}},{{c,atom,[peerhost],unknown},mandatory,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown}},{{c,atom,[protocol],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[sockport],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[username],unknown},mandatory,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}},{{c,atom,[ws_cookie],unknown},optional,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}},{{c,atom,[zone],unknown},mandatory,{c,atom,any,unknown}}],{c,atom,any,unknown},any},unknown}]},{emqx_conf_proto_v3,get_hocon_config,1} => {any,[{c,atom,any,unknown}]},{emqx_node_rebalance_proto_v2,purge_sessions,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,number,{int_rng,0,pos_inf},integer}]},{emqx_management_proto_v2,broker_info,1} => {any,[{c,atom,any,unknown}]},{emqx_node_rebalance_proto_v2,disable_rebalance_agent,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,identifier,[pid],unknown}]},{emqx_trace,trace_file_detail,1} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,map,{[{{c,atom,[file],unknown},mandatory,{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[{c,atom,any,unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},{c,number,{int_rng,0,1114111},integer},none,none,none,none],unknown},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}},{{c,atom,[node],unknown},mandatory,{c,binary,[8,0],unknown}},{{c,atom,[reason],unknown},mandatory,{c,atom,any,unknown}}],none,none},unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,map,{[{{c,atom,[mtime],unknown},mandatory,{c,union,[{c,atom,[undefined],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},{c,tuple,[{c,tuple,[any,any,any],{3,any}},{c,tuple,[any,any,any],{3,any}}],{2,any}},none,none,none],unknown}},{{c,atom,[node],unknown},mandatory,{c,binary,[8,0],unknown}},{{c,atom,[size],unknown},mandatory,{c,union,[{c,atom,[undefined],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown}}],none,none},unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[{c,atom,any,unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},{c,number,{int_rng,0,1114111},integer},none,none,none,none],unknown},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_delayed,clear_all_local,0} => {{c,atom,[ok],unknown},[]},{emqx_topic_metrics_proto_v1,reset,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_node_rebalance,is_node_available,0} => {{c,atom,any,unknown},[]},{emqx_conf_app,get_override_config_file,0} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,map,{[{{c,atom,[msg],unknown},mandatory,any},{{c,atom,[node],unknown},mandatory,{c,atom,any,unknown}}],none,none},unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},any],{2,{c,atom,[ok],unknown}}}]}],unknown},[]},{emqx_node_rebalance_status_proto_v2,local_status,1} => {any,[{c,atom,any,unknown}]},{emqx_node_rebalance_api_proto_v1,node_rebalance_stop,1} => {any,[{c,atom,any,unknown}]},{emqx_gateway_cm_proto_v1,set_chan_info,4} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown},{c,map,{[],{c,atom,any,unknown},any},unknown}]},{emqx_bridge_proto_v4,stop_bridges_to_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_mgmt_api_listeners,do_list_listeners,0} => {{c,map,{[],{c,binary,"( ",unknown},{c,union,[{c,atom,any,unknown},none,none,none,{c,list,[{c,map,{[],any,any},unknown},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}},unknown},[]},{emqx_cm,do_get_chann_conn_mod,2} => {any,[any,any]},{emqx_broker_proto_v1,forward,3} => {any,[{c,atom,any,unknown},{c,binary,[8,0],unknown},{c,tuple,[{c,atom,[delivery],unknown},{c,identifier,[pid],unknown},{c,tuple,[{c,atom,[message],unknown},{c,binary,[8,0],unknown},any,{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,map,{[],{c,atom,any,unknown},{c,atom,[false,true],unknown}},unknown},{c,map,{[{{c,atom,[allow_publish],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[peerhost],unknown},optional,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown}},{{c,atom,[properties],unknown},optional,{c,map,{[],{c,atom,any,unknown},any},unknown}},{{c,atom,[proto_ver],unknown},optional,{c,union,[none,{c,binary,[8,0],unknown},none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown}},{{c,atom,[protocol],unknown},optional,{c,atom,any,unknown}},{{c,atom,[username],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}}],{c,atom,any,unknown},any},unknown},{c,binary,[8,0],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},{c,number,{int_rng,0,255},integer},none,none,none,none],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},none,none,none,none,none],unknown},{c,number,any,integer},any],{10,{c,atom,[message],unknown}}}],{3,{c,atom,[delivery],unknown}}}]},{emqx_resource,create_dry_run_local,2} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},none,none,none],unknown},[{c,atom,any,unknown},any]},{emqx_broker_proto_v1,forward_async,3} => {any,[{c,atom,any,unknown},{c,binary,[8,0],unknown},{c,tuple,[{c,atom,[delivery],unknown},{c,identifier,[pid],unknown},{c,tuple,[{c,atom,[message],unknown},{c,binary,[8,0],unknown},any,{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,map,{[],{c,atom,any,unknown},{c,atom,[false,true],unknown}},unknown},{c,map,{[{{c,atom,[allow_publish],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[peerhost],unknown},optional,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown}},{{c,atom,[properties],unknown},optional,{c,map,{[],{c,atom,any,unknown},any},unknown}},{{c,atom,[proto_ver],unknown},optional,{c,union,[none,{c,binary,[8,0],unknown},none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown}},{{c,atom,[protocol],unknown},optional,{c,atom,any,unknown}},{{c,atom,[username],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}}],{c,atom,any,unknown},any},unknown},{c,binary,[8,0],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},{c,number,{int_rng,0,255},integer},none,none,none,none],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},none,none,none,none,none],unknown},{c,number,any,integer},any],{10,{c,atom,[message],unknown}}}],{3,{c,atom,[delivery],unknown}}}]},{emqx_node_rebalance_api_proto_v1,node_rebalance_evacuation_stop,1} => {any,[{c,atom,any,unknown}]},{emqx_bridge_proto_v2,lookup_from_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_node_rebalance_api_proto_v2,node_rebalance_stop,1} => {any,[{c,atom,any,unknown}]},{emqx_bridge_proto_v2,restart_bridges_to_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_proto_v2,is_running,1} => {any,[{c,atom,any,unknown}]},{emqx_node_rebalance_status_proto_v2,purge_status,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_dashboard_proto_v1,do_sample,2} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,1,pos_inf},integer},none,none,none,none],unknown}]},{emqx_management_proto_v4,call_client,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},any]},{emqx_conf_proto_v1,get_config,2} => {any,[{c,atom,any,unknown},{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],unknown}]},{emqx,get_config,2} => {any,[any,any]},{emqx_node_rebalance_proto_v1,enable_rebalance_agent,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,identifier,[pid],unknown}]},{emqx_conf_proto_v3,get_all,1} => {any,[{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],unknown}]},{emqx_management_proto_v2,list_subscriptions,1} => {any,[{c,atom,any,unknown}]},{emqx_node_rebalance_api_proto_v2,node_rebalance_purge_start,2} => {any,[{c,atom,any,unknown},{c,map,{[{{c,atom,[purge_rate],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}}],none,none},unknown}]},{emqx_bridge_proto_v3,restart_bridges_to_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_persistent_session_ds,do_ensure_all_iterators_closed,1} => {{c,atom,[ok],unknown},[{c,binary,[8,0],unknown}]},{emqx_prometheus_proto_v1,start,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_conf_proto_v3,sync_data_from_node,1} => {any,[{c,atom,any,unknown}]},{emqx_management_proto_v1,list_subscriptions,1} => {any,[{c,atom,any,unknown}]},{emqx_dashboard_monitor,current_rate,1} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[badrpc],unknown},any],{2,{c,atom,[badrpc],unknown}}},{c,tuple,[{c,atom,[ok],unknown},any],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,atom,any,unknown}]},{emqx_management_proto_v3,get_full_config,1} => {any,[{c,atom,any,unknown}]},{emqx_retainer_proto_v2,active_mnesia_indices,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_proto_v2,clean_pem_cache,1} => {any,[{c,atom,any,unknown}]},{emqx_retainer_proto_v1,wait_dispatch_complete,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown}]},{emqx_proto_v2,get_metrics,1} => {any,[{c,atom,any,unknown}]},{emqx_topic_metrics_proto_v1,metrics,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,binary,[8,0],unknown}]},{emqx_broker_proto_v1,list_subscriptions_via_topic,2} => {any,[{c,atom,any,unknown},{c,binary,[8,0],unknown}]},{emqx_cm_proto_v2,kick_session,3} => {any,[{c,atom,[discard,kick],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_management_proto_v3,list_listeners,1} => {any,[{c,atom,any,unknown}]},{emqx_node_rebalance_proto_v1,disable_rebalance_agent,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,identifier,[pid],unknown}]},{emqx_trace,trace_file,1} => {{c,tuple_set,[{3,[{c,tuple,[{c,atom,[error],unknown},{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown},{c,atom,any,unknown}],{3,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown},{c,binary,[8,0],unknown}],{3,{c,atom,[ok],unknown}}}]}],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[{c,atom,any,unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},{c,number,{int_rng,0,1114111},integer},none,none,none,none],unknown},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_bridge_proto_v2,stop_bridges_to_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_gateway_cm_proto_v1,kick_session,4} => {any,[{c,atom,any,unknown},{c,atom,[discard,kick],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_ft_storage_exporter_fs_proxy,list_exports_local,1} => {any,[any]},{emqx_gateway_cm_proto_v1,call,4} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown},any]},{emqx_license_proto_v1,remote_connection_counts,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx,get_config,1} => {any,[{c,list,[any,{c,nil,[],unknown}],unknown}]},{emqx_mgmt_api_plugins_proto_v1,describe_package,1} => {any,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_bridge_proto_v2,start_bridges_to_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_mgmt_api_plugins_proto_v2,get_plugins,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_delayed,delete_delayed_message,1} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},{c,atom,[not_found],unknown}],{2,{c,atom,[error],unknown}}},none,none,none],unknown},[any]},{emqx_bridge_proto_v1,stop_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_exhook_mgr,server_hooks_metrics,1} => {any,[any]},{emqx_bridge_proto_v3,lookup_from_all_nodes,3} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_prometheus_proto_v1,stop,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_bridge_resource,restart,2} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},none,none,none],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},{c,number,{int_rng,0,255},integer},none,none,none,none],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},none,none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[any,{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},{c,number,{int_rng,0,255},integer},none,none,none,none],unknown},{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,nil,[],unknown},none,none,none,none,none],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_ft_storage_fs_reader,read,2} => {any,[{c,identifier,[pid],unknown},{c,number,{int_rng,1,pos_inf},integer}]},{emqx_conf_proto_v2,reset,2} => {any,[{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_node_rebalance_proto_v2,session_counts,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]},{emqx_cm_proto_v1,kick_session,3} => {any,[{c,atom,[discard,kick],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_persistent_session_ds_proto_v1,close_iterator,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,binary,[8,0],unknown}]},{emqx_mgmt_api_plugins_proto_v1,install_package,2} => {any,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,binary,[8,0],unknown}]},{emqx_proto_v2,clean_authz_cache,1} => {any,[{c,atom,any,unknown}]},{emqx_mgmt_api_cluster,connected_replicants,0} => {{c,list,[{c,tuple,[{c,atom,any,unknown},{c,atom,any,unknown},{c,identifier,[pid],unknown}],{3,any}},{c,nil,[],unknown}],unknown},[]},{emqx_conf_cli,get_config,0} => {{c,map,{[],any,any},unknown},[]},{emqx_gateway_cm,do_get_chann_conn_mod,3} => {any,[any,any,any]},{emqx_management_proto_v4,unsubscribe,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,binary,[8,0],unknown}]},{emqx_node_rebalance_api_proto_v2,node_rebalance_evacuation_start,2} => {any,[{c,atom,any,unknown},{c,map,{[{{c,atom,[conn_evict_rate],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[migrate_to],unknown},optional,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}},{{c,atom,[server_reference],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}},{{c,atom,[sess_evict_rate],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[wait_health_check],unknown},optional,{c,number,any,unknown}},{{c,atom,[wait_takeover],unknown},optional,{c,number,any,unknown}}],none,none},unknown}]},{emqx_eviction_agent_proto_v2,evict_session_channel,4} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown},{c,map,{[{{c,atom,[clean_start],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[clientid],unknown},optional,{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}},{{c,atom,[conn_mod],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[conn_props],unknown},optional,{c,map,{[],{c,atom,any,unknown},any},unknown}},{{c,atom,[connected],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[connected_at],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[disconnected_at],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[expiry_interval],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[keepalive],unknown},optional,{c,number,{int_rng,0,1114111},integer}},{{c,atom,[peercert],unknown},optional,{c,union,[{c,atom,[nossl,undefined],unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[{c,atom,any,unknown},none,none,none,none,none,{c,tuple,any,{any,any}},none,none,none],unknown},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}},{{c,atom,[peername],unknown},mandatory,{c,tuple,[{c,union,[{c,atom,[local,undefined,unspec],unknown},none,none,none,none,none,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown},none,none,none],unknown},any],{2,any}}},{{c,atom,[proto_name],unknown},optional,{c,binary,[8,0],unknown}},{{c,atom,[proto_ver],unknown},optional,{c,union,[none,{c,binary,[8,0],unknown},none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none,none],unknown}},{{c,atom,[receive_maximum],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[sockname],unknown},mandatory,{c,tuple,[{c,union,[{c,atom,[local,undefined,unspec],unknown},none,none,none,none,none,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown},none,none,none],unknown},any],{2,any}}},{{c,atom,[socktype],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[username],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}}],{c,atom,any,unknown},any},unknown},{c,map,{[{{c,atom,[anonymous],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[auth_result],unknown},optional,{c,atom,[bad_authentication_method,bad_clientid_or_password,bad_username_or_password,banned,client_identifier_not_valid,not_authorized,server_busy,server_unavailable,success],unknown}},{{c,atom,[clientid],unknown},mandatory,{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}},{{c,atom,[cn],unknown},optional,{c,binary,[8,0],unknown}},{{c,atom,[dn],unknown},optional,{c,binary,[8,0],unknown}},{{c,atom,[is_bridge],unknown},mandatory,{c,atom,[false,true],unknown}},{{c,atom,[is_superuser],unknown},mandatory,{c,atom,[false,true],unknown}},{{c,atom,[mountpoint],unknown},mandatory,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}},{{c,atom,[password],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}},{{c,atom,[peerhost],unknown},mandatory,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown}},{{c,atom,[protocol],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[sockport],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[username],unknown},mandatory,{c,union,[{c,atom,[undefined],unknown},{c,binary,[8,0],unknown},none,none,none,none,none,none,none,none],unknown}},{{c,atom,[ws_cookie],unknown},optional,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}},{{c,atom,[zone],unknown},mandatory,{c,atom,any,unknown}}],{c,atom,any,unknown},any},unknown}]},{emqx_conf_proto_v2,update,3} => {any,[{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},any,{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_mgmt_trace_proto_v2,trace_file_detail,2} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown},{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,union,[{c,atom,any,unknown},none,none,none,{c,list,[any,{c,nil,[],unknown}],unknown},{c,number,{int_rng,0,1114111},integer},none,none,none,none],unknown},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown}]},{emqx_mgmt_api_plugins_proto_v1,ensure_action,2} => {any,[{c,union,[none,{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,atom,[restart,start,stop],unknown}]},{emqx_gateway_cm,do_set_chan_stats,4} => {{c,atom,[false,true],unknown},[any,any,any,any]},{emqx_node_rebalance_api_proto_v2,node_rebalance_start,2} => {any,[{c,atom,any,unknown},{c,map,{[{{c,atom,[abs_conn_threshold],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[abs_sess_threshold],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[conn_evict_rate],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[nodes],unknown},optional,{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}},{{c,atom,[rel_conn_threshold],unknown},optional,{c,number,any,unknown}},{{c,atom,[rel_sess_threshold],unknown},optional,{c,number,any,unknown}},{{c,atom,[sess_evict_rate],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[wait_health_check],unknown},optional,{c,number,any,unknown}},{{c,atom,[wait_takeover],unknown},optional,{c,number,any,unknown}}],none,none},unknown}]},{emqx_conf_proto_v2,reset,3} => {any,[{c,atom,any,unknown},{c,list,[{c,union,[{c,atom,any,unknown},{c,binary,[8,0],unknown},none,none,{c,list,[{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}],unknown},none,none,none,none,none],unknown},{c,nil,[],unknown}],nonempty},{c,map,{[{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_gateway_cm,do_lookup_by_clientid,2} => {{c,list,[any,{c,nil,[],unknown}],unknown},[{c,union,[{c,atom,any,unknown},none,none,none,{c,list,[{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}],unknown},{c,number,any,unknown},none,none,none,none],unknown},any]},{emqx_proto_v2,get_stats,1} => {any,[{c,atom,any,unknown}]},{emqx_topic_metrics_proto_v1,metrics,1} => {any,[{c,list,[{c,atom,any,unknown},{c,nil,[],unknown}],unknown}]}}}. diff --git a/apps/emqx/test/emqx_static_checks_data/5.4.bpapi2 b/apps/emqx/test/emqx_static_checks_data/5.4.bpapi2 new file mode 100644 index 000000000..690ca0035 --- /dev/null +++ b/apps/emqx/test/emqx_static_checks_data/5.4.bpapi2 @@ -0,0 +1 @@ +#{release => "5.4",api => #{{emqx_mgmt_api_plugins,1} => #{calls => [{{emqx_mgmt_api_plugins_proto_v1,ensure_action,['Name','Action']},{emqx_mgmt_api_plugins,ensure_action,['Name','Action']}},{{emqx_mgmt_api_plugins_proto_v1,delete_package,['Name']},{emqx_mgmt_api_plugins,delete_package,['Name']}},{{emqx_mgmt_api_plugins_proto_v1,describe_package,['Name']},{emqx_mgmt_api_plugins,describe_package,['Name']}},{{emqx_mgmt_api_plugins_proto_v1,install_package,['Filename','Bin']},{emqx_mgmt_api_plugins,install_package,['Filename','Bin']}},{{emqx_mgmt_api_plugins_proto_v1,get_plugins,[]},{emqx_mgmt_api_plugins,get_plugins,[]}}],casts => []},{emqx,1} => #{calls => [{{emqx_proto_v1,delete_all_deactivated_alarms,['Node']},{emqx_alarm,delete_all_deactivated_alarms,[]}},{{emqx_proto_v1,deactivate_alarm,['Node','Name']},{emqx_alarm,deactivate,['Name']}},{{emqx_proto_v1,clean_pem_cache,['Node']},{ssl_pem_cache,clear,[]}},{{emqx_proto_v1,clean_authz_cache,['Node']},{emqx_authz_cache,drain_cache,[]}},{{emqx_proto_v1,clean_authz_cache,['Node','ClientId']},{emqx_authz_cache,drain_cache,['ClientId']}},{{emqx_proto_v1,get_metrics,['Node']},{emqx_metrics,all,[]}},{{emqx_proto_v1,get_stats,['Node']},{emqx_stats,getstats,[]}},{{emqx_proto_v1,get_alarms,['Node','Type']},{emqx_alarm,get_alarms,['Type']}},{{emqx_proto_v1,is_running,['Node']},{emqx,is_running,[]}}],casts => []},{emqx_bridge,4} => #{calls => [{{emqx_bridge_proto_v4,get_metrics_from_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_api,get_metrics_from_local_node,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v4,lookup_from_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_api,lookup_from_local_node,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v4,stop_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,stop,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v4,start_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,start,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v4,restart_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,restart,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v4,stop_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,stop,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v4,start_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,start,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v4,restart_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,restart,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v4,list_bridges_on_nodes,['Nodes']},{emqx_bridge,list,[]}}],casts => []},{emqx_mgmt_trace,1} => #{calls => [{{emqx_mgmt_trace_proto_v1,read_trace_file,['Node','Name','Position','Limit']},{emqx_mgmt_api_trace,read_trace_file,['Name','Position','Limit']}},{{emqx_mgmt_trace_proto_v1,trace_file,['Nodes','File']},{emqx_trace,trace_file,['File']}},{{emqx_mgmt_trace_proto_v1,get_trace_size,['Nodes']},{emqx_mgmt_api_trace,get_trace_size,[]}}],casts => []},{emqx_management,2} => #{calls => [{{emqx_management_proto_v2,get_full_config,['Node']},{emqx_mgmt_api_configs,get_full_config,[]}},{{emqx_management_proto_v2,call_client,['Node','ClientId','Req']},{emqx_mgmt,do_call_client,['ClientId','Req']}},{{emqx_management_proto_v2,unsubscribe,['Node','ClientId','Topic']},{emqx_mgmt,do_unsubscribe,['ClientId','Topic']}},{{emqx_management_proto_v2,subscribe,['Node','ClientId','TopicTables']},{emqx_mgmt,do_subscribe,['ClientId','TopicTables']}},{{emqx_management_proto_v2,list_listeners,['Node']},{emqx_mgmt_api_listeners,do_list_listeners,[]}},{{emqx_management_proto_v2,list_subscriptions,['Node']},{emqx_mgmt,do_list_subscriptions,[]}},{{emqx_management_proto_v2,broker_info,['Node']},{emqx_mgmt,broker_info,[]}},{{emqx_management_proto_v2,node_info,['Node']},{emqx_mgmt,node_info,[]}},{{emqx_management_proto_v2,unsubscribe_batch,['Node','ClientId','Topics']},{emqx_mgmt,do_unsubscribe_batch,['ClientId','Topics']}}],casts => []},{emqx_bridge,2} => #{calls => [{{emqx_bridge_proto_v2,lookup_from_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_api,lookup_from_local_node,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v2,stop_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,stop,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v2,start_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,start,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v2,restart_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,restart,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v2,stop_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,stop,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v2,start_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,start,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v2,restart_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,restart,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v2,list_bridges,['Node']},{emqx_bridge,list,[]}}],casts => []},{emqx_node_rebalance_status,2} => #{calls => [{{emqx_node_rebalance_status_proto_v2,purge_status,['Nodes']},{emqx_node_rebalance_status,purge_status,[]}},{{emqx_node_rebalance_status_proto_v2,evacuation_status,['Nodes']},{emqx_node_rebalance_status,evacuation_status,[]}},{{emqx_node_rebalance_status_proto_v2,rebalance_status,['Nodes']},{emqx_node_rebalance_status,rebalance_status,[]}},{{emqx_node_rebalance_status_proto_v2,local_status,['Node']},{emqx_node_rebalance_status,local_status,[]}}],casts => []},{emqx_prometheus,1} => #{calls => [{{emqx_prometheus_proto_v1,stop,['Nodes']},{emqx_prometheus,do_stop,[]}},{{emqx_prometheus_proto_v1,start,['Nodes']},{emqx_prometheus,do_start,[]}}],casts => []},{emqx_resource,1} => #{calls => [{{emqx_resource_proto_v1,reset_metrics,['ResId']},{emqx_resource,reset_metrics_local,['ResId']}},{{emqx_resource_proto_v1,remove,['ResId']},{emqx_resource,remove_local,['ResId']}},{{emqx_resource_proto_v1,recreate,['ResId','ResourceType','Config','Opts']},{emqx_resource,recreate_local,['ResId','ResourceType','Config','Opts']}},{{emqx_resource_proto_v1,create_dry_run,['ResourceType','Config']},{emqx_resource,create_dry_run_local,['ResourceType','Config']}},{{emqx_resource_proto_v1,create,['ResId','Group','ResourceType','Config','Opts']},{emqx_resource,create_local,['ResId','Group','ResourceType','Config','Opts']}}],casts => []},{emqx_node_rebalance_purge,1} => #{calls => [{{emqx_node_rebalance_purge_proto_v1,stop,['Nodes']},{emqx_node_rebalance_purge,stop,[]}},{{emqx_node_rebalance_purge_proto_v1,start,['Nodes','Opts']},{emqx_node_rebalance_purge,start,['Opts']}}],casts => []},{emqx_topic_metrics,1} => #{calls => [{{emqx_topic_metrics_proto_v1,reset,['Nodes','Topic']},{emqx_topic_metrics,reset,['Topic']}},{{emqx_topic_metrics_proto_v1,reset,['Nodes']},{emqx_topic_metrics,reset,[]}},{{emqx_topic_metrics_proto_v1,metrics,['Nodes','Topic']},{emqx_topic_metrics,metrics,['Topic']}},{{emqx_topic_metrics_proto_v1,metrics,['Nodes']},{emqx_topic_metrics,metrics,[]}}],casts => []},{emqx_management,1} => #{calls => [{{emqx_management_proto_v1,get_full_config,['Node']},{emqx_mgmt_api_configs,get_full_config,[]}},{{emqx_management_proto_v1,call_client,['Node','ClientId','Req']},{emqx_mgmt,do_call_client,['ClientId','Req']}},{{emqx_management_proto_v1,unsubscribe,['Node','ClientId','Topic']},{emqx_mgmt,do_unsubscribe,['ClientId','Topic']}},{{emqx_management_proto_v1,subscribe,['Node','ClientId','TopicTables']},{emqx_mgmt,do_subscribe,['ClientId','TopicTables']}},{{emqx_management_proto_v1,list_listeners,['Node']},{emqx_mgmt_api_listeners,do_list_listeners,[]}},{{emqx_management_proto_v1,list_subscriptions,['Node']},{emqx_mgmt,do_list_subscriptions,[]}},{{emqx_management_proto_v1,broker_info,['Node']},{emqx_mgmt,broker_info,[]}},{{emqx_management_proto_v1,node_info,['Node']},{emqx_mgmt,node_info,[]}}],casts => []},{emqx_conf,3} => #{calls => [{{emqx_conf_proto_v3,get_hocon_config,['Node','Key']},{emqx_conf_cli,get_config,['Key']}},{{emqx_conf_proto_v3,get_hocon_config,['Node']},{emqx_conf_cli,get_config,[]}},{{emqx_conf_proto_v3,get_override_config_file,['Nodes']},{emqx_conf_app,get_override_config_file,[]}},{{emqx_conf_proto_v3,reset,['Node','KeyPath','Opts']},{emqx,reset_config,['KeyPath','Opts']}},{{emqx_conf_proto_v3,reset,['KeyPath','Opts']},{emqx,reset_config,['KeyPath','Opts']}},{{emqx_conf_proto_v3,remove_config,['Node','KeyPath','Opts']},{emqx,remove_config,['KeyPath','Opts']}},{{emqx_conf_proto_v3,remove_config,['KeyPath','Opts']},{emqx,remove_config,['KeyPath','Opts']}},{{emqx_conf_proto_v3,update,['Node','KeyPath','UpdateReq','Opts']},{emqx,update_config,['KeyPath','UpdateReq','Opts']}},{{emqx_conf_proto_v3,update,['KeyPath','UpdateReq','Opts']},{emqx,update_config,['KeyPath','UpdateReq','Opts']}},{{emqx_conf_proto_v3,get_all,['KeyPath']},{emqx_conf,get_node_and_config,['KeyPath']}},{{emqx_conf_proto_v3,get_config,['Node','KeyPath','Default']},{emqx,get_config,['KeyPath','Default']}},{{emqx_conf_proto_v3,get_config,['Node','KeyPath']},{emqx,get_config,['KeyPath']}},{{emqx_conf_proto_v3,sync_data_from_node,['Node']},{emqx_conf_app,sync_data_from_node,[]}}],casts => []},{emqx_plugins,1} => #{calls => [{{emqx_plugins_proto_v1,get_tar,['Node','NameVsn','Timeout']},{emqx_plugins,get_tar,['NameVsn']}}],casts => []},{emqx_cm,1} => #{calls => [{{emqx_cm_proto_v1,kick_session,['Action','ClientId','ChanPid']},{emqx_cm,do_kick_session,['Action','ClientId','ChanPid']}},{{emqx_cm_proto_v1,takeover_session,['ClientId','ChanPid']},{emqx_cm,takeover_session,['ClientId','ChanPid']}},{{emqx_cm_proto_v1,get_chann_conn_mod,['ClientId','ChanPid']},{emqx_cm,do_get_chann_conn_mod,['ClientId','ChanPid']}},{{emqx_cm_proto_v1,get_chan_info,['ClientId','ChanPid']},{emqx_cm,do_get_chan_info,['ClientId','ChanPid']}},{{emqx_cm_proto_v1,get_chan_stats,['ClientId','ChanPid']},{emqx_cm,do_get_chan_stats,['ClientId','ChanPid']}},{{emqx_cm_proto_v1,lookup_client,['Node','Key']},{emqx_cm,lookup_client,['Key']}},{{emqx_cm_proto_v1,kickout_client,['Node','ClientId']},{emqx_cm,kick_session,['ClientId']}}],casts => []},{emqx_delayed,1} => #{calls => [{{emqx_delayed_proto_v1,delete_delayed_message,['Node','Id']},{emqx_delayed,delete_delayed_message,['Id']}},{{emqx_delayed_proto_v1,get_delayed_message,['Node','Id']},{emqx_delayed,get_delayed_message,['Id']}}],casts => []},{emqx_persistent_session_ds,1} => #{calls => [{{emqx_persistent_session_ds_proto_v1,close_all_iterators,['Nodes','DSSessionID']},{emqx_persistent_session_ds,do_ensure_all_iterators_closed,['DSSessionID']}},{{emqx_persistent_session_ds_proto_v1,close_iterator,['Nodes','IteratorID']},{emqx_persistent_session_ds,do_ensure_iterator_closed,['IteratorID']}},{{emqx_persistent_session_ds_proto_v1,open_iterator,['Nodes','TopicFilter','StartMS','IteratorID']},{emqx_persistent_session_ds,do_open_iterator,['TopicFilter','StartMS','IteratorID']}}],casts => []},{emqx_dashboard,1} => #{calls => [{{emqx_dashboard_proto_v1,current_rate,['Node']},{emqx_dashboard_monitor,current_rate,['Node']}},{{emqx_dashboard_proto_v1,do_sample,['Node','Latest']},{emqx_dashboard_monitor,do_sample,['Node','Latest']}}],casts => []},{emqx_gateway_api_listeners,1} => #{calls => [{{emqx_gateway_api_listeners_proto_v1,listeners_cluster_status,['Nodes','Listeners']},{emqx_gateway_api_listeners,do_listeners_cluster_status,['Listeners']}}],casts => []},{emqx_eviction_agent,1} => #{calls => [{{emqx_eviction_agent_proto_v1,evict_session_channel,['Node','ClientId','ConnInfo','ClientInfo']},{emqx_eviction_agent,evict_session_channel,['ClientId','ConnInfo','ClientInfo']}}],casts => []},{emqx_ft_storage_fs,1} => #{calls => [{{emqx_ft_storage_fs_proto_v1,list_assemblers,['Nodes','Transfer']},{emqx_ft_storage_fs_proxy,lookup_local_assembler,['Transfer']}},{{emqx_ft_storage_fs_proto_v1,pread,['Node','Transfer','Frag','Offset','Size']},{emqx_ft_storage_fs_proxy,pread_local,['Transfer','Frag','Offset','Size']}},{{emqx_ft_storage_fs_proto_v1,multilist,['Nodes','Transfer','What']},{emqx_ft_storage_fs_proxy,list_local,['Transfer','What']}}],casts => []},{emqx_node_rebalance,1} => #{calls => [{{emqx_node_rebalance_proto_v1,disconnected_session_counts,['Nodes']},{emqx_node_rebalance,disconnected_session_count,[]}},{{emqx_node_rebalance_proto_v1,disable_rebalance_agent,['Nodes','OwnerPid']},{emqx_node_rebalance_agent,disable,['OwnerPid']}},{{emqx_node_rebalance_proto_v1,enable_rebalance_agent,['Nodes','OwnerPid']},{emqx_node_rebalance_agent,enable,['OwnerPid']}},{{emqx_node_rebalance_proto_v1,session_counts,['Nodes']},{emqx_node_rebalance,session_count,[]}},{{emqx_node_rebalance_proto_v1,connection_counts,['Nodes']},{emqx_node_rebalance,connection_count,[]}},{{emqx_node_rebalance_proto_v1,evict_sessions,['Nodes','Count','RecipientNodes','ConnState']},{emqx_eviction_agent,evict_sessions,['Count','RecipientNodes','ConnState']}},{{emqx_node_rebalance_proto_v1,evict_connections,['Nodes','Count']},{emqx_eviction_agent,evict_connections,['Count']}},{{emqx_node_rebalance_proto_v1,available_nodes,['Nodes']},{emqx_node_rebalance,is_node_available,[]}}],casts => []},{emqx_rule_engine,1} => #{calls => [{{emqx_rule_engine_proto_v1,reset_metrics,['RuleId']},{emqx_rule_engine,reset_metrics_for_rule,['RuleId']}}],casts => []},{emqx_ft_storage_exporter_fs,1} => #{calls => [{{emqx_ft_storage_exporter_fs_proto_v1,read_export_file,['Node','Filepath','CallerPid']},{emqx_ft_storage_exporter_fs_proxy,read_export_file_local,['Filepath','CallerPid']}},{{emqx_ft_storage_exporter_fs_proto_v1,list_exports,['Nodes','Query']},{emqx_ft_storage_exporter_fs_proxy,list_exports_local,['Query']}}],casts => []},{emqx_conf,2} => #{calls => [{{emqx_conf_proto_v2,get_override_config_file,['Nodes']},{emqx_conf_app,get_override_config_file,[]}},{{emqx_conf_proto_v2,reset,['Node','KeyPath','Opts']},{emqx,reset_config,['KeyPath','Opts']}},{{emqx_conf_proto_v2,reset,['KeyPath','Opts']},{emqx,reset_config,['KeyPath','Opts']}},{{emqx_conf_proto_v2,remove_config,['Node','KeyPath','Opts']},{emqx,remove_config,['KeyPath','Opts']}},{{emqx_conf_proto_v2,remove_config,['KeyPath','Opts']},{emqx,remove_config,['KeyPath','Opts']}},{{emqx_conf_proto_v2,update,['Node','KeyPath','UpdateReq','Opts']},{emqx,update_config,['KeyPath','UpdateReq','Opts']}},{{emqx_conf_proto_v2,update,['KeyPath','UpdateReq','Opts']},{emqx,update_config,['KeyPath','UpdateReq','Opts']}},{{emqx_conf_proto_v2,get_all,['KeyPath']},{emqx_conf,get_node_and_config,['KeyPath']}},{{emqx_conf_proto_v2,get_config,['Node','KeyPath','Default']},{emqx,get_config,['KeyPath','Default']}},{{emqx_conf_proto_v2,get_config,['Node','KeyPath']},{emqx,get_config,['KeyPath']}},{{emqx_conf_proto_v2,sync_data_from_node,['Node']},{emqx_conf_app,sync_data_from_node,[]}}],casts => []},{emqx_authz,1} => #{calls => [{{emqx_authz_proto_v1,lookup_from_all_nodes,['Nodes','Type']},{emqx_authz_api_sources,lookup_from_local_node,['Type']}}],casts => []},{emqx_node_rebalance_api,2} => #{calls => [{{emqx_node_rebalance_api_proto_v2,node_rebalance_purge_stop,['Node']},{emqx_node_rebalance_purge,stop,[]}},{{emqx_node_rebalance_api_proto_v2,node_rebalance_purge_start,['Node','Opts']},{emqx_node_rebalance_purge,start,['Opts']}},{{emqx_node_rebalance_api_proto_v2,node_rebalance_stop,['Node']},{emqx_node_rebalance,stop,[]}},{{emqx_node_rebalance_api_proto_v2,node_rebalance_start,['Node','Opts']},{emqx_node_rebalance,start,['Opts']}},{{emqx_node_rebalance_api_proto_v2,node_rebalance_evacuation_stop,['Node']},{emqx_node_rebalance_evacuation,stop,[]}},{{emqx_node_rebalance_api_proto_v2,node_rebalance_evacuation_start,['Node','Opts']},{emqx_node_rebalance_evacuation,start,['Opts']}}],casts => []},{emqx_delayed,2} => #{calls => [{{emqx_delayed_proto_v2,clear_all,['Nodes']},{emqx_delayed,clear_all_local,[]}},{{emqx_delayed_proto_v2,delete_delayed_message,['Node','Id']},{emqx_delayed,delete_delayed_message,['Id']}},{{emqx_delayed_proto_v2,get_delayed_message,['Node','Id']},{emqx_delayed,get_delayed_message,['Id']}}],casts => []},{emqx_cm,2} => #{calls => [{{emqx_cm_proto_v2,kick_session,['Action','ClientId','ChanPid']},{emqx_cm,do_kick_session,['Action','ClientId','ChanPid']}},{{emqx_cm_proto_v2,takeover_finish,['ConnMod','ChanPid']},{emqx_cm,takeover_finish,['ConnMod','ChanPid']}},{{emqx_cm_proto_v2,takeover_session,['ClientId','ChanPid']},{emqx_cm,takeover_session,['ClientId','ChanPid']}},{{emqx_cm_proto_v2,get_chann_conn_mod,['ClientId','ChanPid']},{emqx_cm,do_get_chann_conn_mod,['ClientId','ChanPid']}},{{emqx_cm_proto_v2,get_chan_info,['ClientId','ChanPid']},{emqx_cm,do_get_chan_info,['ClientId','ChanPid']}},{{emqx_cm_proto_v2,get_chan_stats,['ClientId','ChanPid']},{emqx_cm,do_get_chan_stats,['ClientId','ChanPid']}},{{emqx_cm_proto_v2,lookup_client,['Node','Key']},{emqx_cm,lookup_client,['Key']}},{{emqx_cm_proto_v2,kickout_client,['Node','ClientId']},{emqx_cm,kick_session,['ClientId']}}],casts => []},{emqx_gateway_cm,1} => #{calls => [{{emqx_gateway_cm_proto_v1,cast,['GwName','ClientId','ChanPid','Req']},{emqx_gateway_cm,do_cast,['GwName','ClientId','ChanPid','Req']}},{{emqx_gateway_cm_proto_v1,call,['GwName','ClientId','ChanPid','Req']},{emqx_gateway_cm,do_call,['GwName','ClientId','ChanPid','Req']}},{{emqx_gateway_cm_proto_v1,call,['GwName','ClientId','ChanPid','Req','Timeout']},{emqx_gateway_cm,do_call,['GwName','ClientId','ChanPid','Req','Timeout']}},{{emqx_gateway_cm_proto_v1,takeover_session,['GwName','ClientId','ChanPid']},{emqx_gateway_cm,do_takeover_session,['GwName','ClientId','ChanPid']}},{{emqx_gateway_cm_proto_v1,get_chann_conn_mod,['GwName','ClientId','ChanPid']},{emqx_gateway_cm,do_get_chann_conn_mod,['GwName','ClientId','ChanPid']}},{{emqx_gateway_cm_proto_v1,kick_session,['GwName','Action','ClientId','ChanPid']},{emqx_gateway_cm,do_kick_session,['GwName','Action','ClientId','ChanPid']}},{{emqx_gateway_cm_proto_v1,set_chan_stats,['GwName','ClientId','ChanPid','Stats']},{emqx_gateway_cm,do_set_chan_stats,['GwName','ClientId','ChanPid','Stats']}},{{emqx_gateway_cm_proto_v1,get_chan_stats,['GwName','ClientId','ChanPid']},{emqx_gateway_cm,do_get_chan_stats,['GwName','ClientId','ChanPid']}},{{emqx_gateway_cm_proto_v1,set_chan_info,['GwName','ClientId','ChanPid','Infos']},{emqx_gateway_cm,do_set_chan_info,['GwName','ClientId','ChanPid','Infos']}},{{emqx_gateway_cm_proto_v1,get_chan_info,['GwName','ClientId','ChanPid']},{emqx_gateway_cm,do_get_chan_info,['GwName','ClientId','ChanPid']}},{{emqx_gateway_cm_proto_v1,lookup_by_clientid,['Nodes','GwName','ClientId']},{emqx_gateway_cm,do_lookup_by_clientid,['GwName','ClientId']}}],casts => []},{emqx_license,1} => #{calls => [{{emqx_license_proto_v1,remote_connection_counts,['Nodes']},{emqx_license_resources,local_connection_count,[]}}],casts => []},{emqx_license,2} => #{calls => [{{emqx_license_proto_v2,remote_connection_counts,['Nodes']},{emqx_license_resources,local_connection_count,[]}}],casts => []},{emqx_telemetry,1} => #{calls => [{{emqx_telemetry_proto_v1,get_cluster_uuid,['Node']},{emqx_telemetry,get_cluster_uuid,[]}},{{emqx_telemetry_proto_v1,get_node_uuid,['Node']},{emqx_telemetry,get_node_uuid,[]}}],casts => []},{emqx_conf,1} => #{calls => [{{emqx_conf_proto_v1,get_override_config_file,['Nodes']},{emqx_conf_app,get_override_config_file,[]}},{{emqx_conf_proto_v1,reset,['Node','KeyPath','Opts']},{emqx,reset_config,['KeyPath','Opts']}},{{emqx_conf_proto_v1,reset,['KeyPath','Opts']},{emqx,reset_config,['KeyPath','Opts']}},{{emqx_conf_proto_v1,remove_config,['Node','KeyPath','Opts']},{emqx,remove_config,['KeyPath','Opts']}},{{emqx_conf_proto_v1,remove_config,['KeyPath','Opts']},{emqx,remove_config,['KeyPath','Opts']}},{{emqx_conf_proto_v1,update,['Node','KeyPath','UpdateReq','Opts']},{emqx,update_config,['KeyPath','UpdateReq','Opts']}},{{emqx_conf_proto_v1,update,['KeyPath','UpdateReq','Opts']},{emqx,update_config,['KeyPath','UpdateReq','Opts']}},{{emqx_conf_proto_v1,get_all,['KeyPath']},{emqx_conf,get_node_and_config,['KeyPath']}},{{emqx_conf_proto_v1,get_config,['Node','KeyPath','Default']},{emqx,get_config,['KeyPath','Default']}},{{emqx_conf_proto_v1,get_config,['Node','KeyPath']},{emqx,get_config,['KeyPath']}}],casts => []},{emqx_authn,1} => #{calls => [{{emqx_authn_proto_v1,lookup_from_all_nodes,['Nodes','ChainName','AuthenticatorID']},{emqx_authn_api,lookup_from_local_node,['ChainName','AuthenticatorID']}}],casts => []},{emqx_node_rebalance_evacuation,1} => #{calls => [{{emqx_node_rebalance_evacuation_proto_v1,available_nodes,['Nodes']},{emqx_node_rebalance_evacuation,is_node_available,[]}}],casts => []},{emqx_node_rebalance_status,1} => #{calls => [{{emqx_node_rebalance_status_proto_v1,evacuation_status,['Nodes']},{emqx_node_rebalance_status,evacuation_status,[]}},{{emqx_node_rebalance_status_proto_v1,rebalance_status,['Nodes']},{emqx_node_rebalance_status,rebalance_status,[]}},{{emqx_node_rebalance_status_proto_v1,local_status,['Node']},{emqx_node_rebalance_status,local_status,[]}}],casts => []},{emqx_bridge,1} => #{calls => [{{emqx_bridge_proto_v1,lookup_from_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_api,lookup_from_local_node,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v1,stop_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,stop,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v1,restart_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,restart,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v1,stop_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,stop,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v1,restart_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,restart,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v1,list_bridges,['Node']},{emqx_bridge,list,[]}}],casts => []},{emqx_bridge,5} => #{calls => [{{emqx_bridge_proto_v5,v2_start_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_v2,start,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v5,v2_start_bridge_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_v2,start,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v5,v2_get_metrics_from_all_nodes,['Nodes','ActionType','ActionName']},{emqx_bridge_v2_api,get_metrics_from_local_node,['ActionType','ActionName']}},{{emqx_bridge_proto_v5,v2_lookup_from_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_v2_api,lookup_from_local_node,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v5,v2_list_bridges_on_nodes,['Nodes']},{emqx_bridge_v2,list,[]}},{{emqx_bridge_proto_v5,get_metrics_from_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_api,get_metrics_from_local_node,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v5,lookup_from_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_api,lookup_from_local_node,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v5,stop_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,stop,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v5,start_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,start,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v5,restart_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,restart,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v5,stop_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,stop,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v5,start_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,start,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v5,restart_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,restart,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v5,list_bridges_on_nodes,['Nodes']},{emqx_bridge,list,[]}}],casts => []},{emqx_bridge,3} => #{calls => [{{emqx_bridge_proto_v3,lookup_from_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_api,lookup_from_local_node,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v3,stop_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,stop,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v3,start_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,start,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v3,restart_bridges_to_all_nodes,['Nodes','BridgeType','BridgeName']},{emqx_bridge_resource,restart,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v3,stop_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,stop,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v3,start_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,start,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v3,restart_bridge_to_node,['Node','BridgeType','BridgeName']},{emqx_bridge_resource,restart,['BridgeType','BridgeName']}},{{emqx_bridge_proto_v3,list_bridges_on_nodes,['Nodes']},{emqx_bridge,list,[]}},{{emqx_bridge_proto_v3,list_bridges,['Node']},{emqx_bridge,list,[]}}],casts => []},{emqx_exhook,1} => #{calls => [{{emqx_exhook_proto_v1,server_hooks_metrics,['Nodes','Name']},{emqx_exhook_mgr,server_hooks_metrics,['Name']}},{{emqx_exhook_proto_v1,server_info,['Nodes','Name']},{emqx_exhook_mgr,server_info,['Name']}},{{emqx_exhook_proto_v1,all_servers_info,['Nodes']},{emqx_exhook_mgr,all_servers_info,[]}}],casts => []},{emqx_retainer,2} => #{calls => [{{emqx_retainer_proto_v2,active_mnesia_indices,['Nodes']},{emqx_retainer_mnesia,active_indices,[]}},{{emqx_retainer_proto_v2,wait_dispatch_complete,['Nodes','Timeout']},{emqx_retainer_dispatcher,wait_dispatch_complete,['Timeout']}}],casts => []},{emqx_connector,1} => #{calls => [{{emqx_connector_proto_v1,start_connectors_to_all_nodes,['Nodes','ConnectorType','ConnectorName']},{emqx_connector_resource,start,['ConnectorType','ConnectorName']}},{{emqx_connector_proto_v1,start_connector_to_node,['Node','ConnectorType','ConnectorName']},{emqx_connector_resource,start,['ConnectorType','ConnectorName']}},{{emqx_connector_proto_v1,lookup_from_all_nodes,['Nodes','ConnectorType','ConnectorName']},{emqx_connector_api,lookup_from_local_node,['ConnectorType','ConnectorName']}},{{emqx_connector_proto_v1,list_connectors_on_nodes,['Nodes']},{emqx_connector,list,[]}}],casts => []},{emqx_retainer,1} => #{calls => [{{emqx_retainer_proto_v1,wait_dispatch_complete,['Nodes','Timeout']},{emqx_retainer_dispatcher,wait_dispatch_complete,['Timeout']}}],casts => []},{emqx_ft_storage_fs_reader,1} => #{calls => [{{emqx_ft_storage_fs_reader_proto_v1,read,['Node','Pid','Bytes']},{emqx_ft_storage_fs_reader,read,['Pid','Bytes']}}],casts => []},{emqx_node_rebalance,3} => #{calls => [{{emqx_node_rebalance_proto_v3,enable_rebalance_agent,['Nodes','OwnerPid','Kind','Options']},{emqx_node_rebalance_agent,enable,['OwnerPid','Kind','Options']}},{{emqx_node_rebalance_proto_v3,purge_sessions,['Nodes','Count']},{emqx_eviction_agent,purge_sessions,['Count']}},{{emqx_node_rebalance_proto_v3,disable_rebalance_agent,['Nodes','OwnerPid','Kind']},{emqx_node_rebalance_agent,disable,['OwnerPid','Kind']}},{{emqx_node_rebalance_proto_v3,enable_rebalance_agent,['Nodes','OwnerPid','Kind']},{emqx_node_rebalance_agent,enable,['OwnerPid','Kind']}},{{emqx_node_rebalance_proto_v3,disconnected_session_counts,['Nodes']},{emqx_node_rebalance,disconnected_session_count,[]}},{{emqx_node_rebalance_proto_v3,disable_rebalance_agent,['Nodes','OwnerPid']},{emqx_node_rebalance_agent,disable,['OwnerPid']}},{{emqx_node_rebalance_proto_v3,enable_rebalance_agent,['Nodes','OwnerPid']},{emqx_node_rebalance_agent,enable,['OwnerPid']}},{{emqx_node_rebalance_proto_v3,session_counts,['Nodes']},{emqx_node_rebalance,session_count,[]}},{{emqx_node_rebalance_proto_v3,connection_counts,['Nodes']},{emqx_node_rebalance,connection_count,[]}},{{emqx_node_rebalance_proto_v3,evict_sessions,['Nodes','Count','RecipientNodes','ConnState']},{emqx_eviction_agent,evict_sessions,['Count','RecipientNodes','ConnState']}},{{emqx_node_rebalance_proto_v3,evict_connections,['Nodes','Count']},{emqx_eviction_agent,evict_connections,['Count']}},{{emqx_node_rebalance_proto_v3,available_nodes,['Nodes']},{emqx_node_rebalance,is_node_available,[]}}],casts => []},{emqx_mgmt_data_backup,1} => #{calls => [{{emqx_mgmt_data_backup_proto_v1,delete_file,['Node','FileName','Timeout']},{emqx_mgmt_data_backup,delete_file,['FileName']}},{{emqx_mgmt_data_backup_proto_v1,read_file,['Node','FileName','Timeout']},{emqx_mgmt_data_backup,read_file,['FileName']}},{{emqx_mgmt_data_backup_proto_v1,import_file,['Node','FileNode','FileName','Timeout']},{emqx_mgmt_data_backup,maybe_copy_and_import,['FileNode','FileName']}},{{emqx_mgmt_data_backup_proto_v1,list_files,['Nodes','Timeout']},{emqx_mgmt_data_backup,list_files,[]}}],casts => []},{emqx_eviction_agent,2} => #{calls => [{{emqx_eviction_agent_proto_v2,all_channels_count,['Nodes','Timeout']},{emqx_eviction_agent,all_local_channels_count,[]}},{{emqx_eviction_agent_proto_v2,evict_session_channel,['Node','ClientId','ConnInfo','ClientInfo']},{emqx_eviction_agent,evict_session_channel,['ClientId','ConnInfo','ClientInfo']}}],casts => []},{emqx_node_rebalance_api,1} => #{calls => [{{emqx_node_rebalance_api_proto_v1,node_rebalance_stop,['Node']},{emqx_node_rebalance,stop,[]}},{{emqx_node_rebalance_api_proto_v1,node_rebalance_start,['Node','Opts']},{emqx_node_rebalance,start,['Opts']}},{{emqx_node_rebalance_api_proto_v1,node_rebalance_evacuation_stop,['Node']},{emqx_node_rebalance_evacuation,stop,[]}},{{emqx_node_rebalance_api_proto_v1,node_rebalance_evacuation_start,['Node','Opts']},{emqx_node_rebalance_evacuation,start,['Opts']}}],casts => []},{emqx_mgmt_cluster,1} => #{calls => [{{emqx_mgmt_cluster_proto_v1,invite_node,['Node','Self']},{emqx_mgmt_api_cluster,join,['Self']}}],casts => []},{emqx_mgmt_cluster,2} => #{calls => [{{emqx_mgmt_cluster_proto_v2,connected_replicants,['Nodes']},{emqx_mgmt_api_cluster,connected_replicants,[]}},{{emqx_mgmt_cluster_proto_v2,invite_node,['Node','Self']},{emqx_mgmt_api_cluster,join,['Self']}}],casts => []},{emqx_slow_subs,1} => #{calls => [{{emqx_slow_subs_proto_v1,get_history,['Nodes']},{emqx_slow_subs_api,get_history,[]}},{{emqx_slow_subs_proto_v1,clear_history,['Nodes']},{emqx_slow_subs,clear_history,[]}}],casts => []},{emqx_management,4} => #{calls => [{{emqx_management_proto_v4,kickout_clients,['Node','ClientIds']},{emqx_mgmt,do_kickout_clients,['ClientIds']}},{{emqx_management_proto_v4,get_full_config,['Node']},{emqx_mgmt_api_configs,get_full_config,[]}},{{emqx_management_proto_v4,call_client,['Node','ClientId','Req']},{emqx_mgmt,do_call_client,['ClientId','Req']}},{{emqx_management_proto_v4,unsubscribe,['Node','ClientId','Topic']},{emqx_mgmt,do_unsubscribe,['ClientId','Topic']}},{{emqx_management_proto_v4,subscribe,['Node','ClientId','TopicTables']},{emqx_mgmt,do_subscribe,['ClientId','TopicTables']}},{{emqx_management_proto_v4,list_listeners,['Node']},{emqx_mgmt_api_listeners,do_list_listeners,[]}},{{emqx_management_proto_v4,list_subscriptions,['Node']},{emqx_mgmt,do_list_subscriptions,[]}},{{emqx_management_proto_v4,broker_info,['Nodes']},{emqx_mgmt,broker_info,[]}},{{emqx_management_proto_v4,node_info,['Nodes']},{emqx_mgmt,node_info,[]}},{{emqx_management_proto_v4,unsubscribe_batch,['Node','ClientId','Topics']},{emqx_mgmt,do_unsubscribe_batch,['ClientId','Topics']}}],casts => []},{emqx_metrics,1} => #{calls => [{{emqx_metrics_proto_v1,get_metrics,['Nodes','HandlerName','MetricId','Timeout']},{emqx_metrics_worker,get_metrics,['HandlerName','MetricId']}}],casts => []},{emqx_management,3} => #{calls => [{{emqx_management_proto_v3,get_full_config,['Node']},{emqx_mgmt_api_configs,get_full_config,[]}},{{emqx_management_proto_v3,call_client,['Node','ClientId','Req']},{emqx_mgmt,do_call_client,['ClientId','Req']}},{{emqx_management_proto_v3,unsubscribe,['Node','ClientId','Topic']},{emqx_mgmt,do_unsubscribe,['ClientId','Topic']}},{{emqx_management_proto_v3,subscribe,['Node','ClientId','TopicTables']},{emqx_mgmt,do_subscribe,['ClientId','TopicTables']}},{{emqx_management_proto_v3,list_listeners,['Node']},{emqx_mgmt_api_listeners,do_list_listeners,[]}},{{emqx_management_proto_v3,list_subscriptions,['Node']},{emqx_mgmt,do_list_subscriptions,[]}},{{emqx_management_proto_v3,broker_info,['Nodes']},{emqx_mgmt,broker_info,[]}},{{emqx_management_proto_v3,node_info,['Nodes']},{emqx_mgmt,node_info,[]}},{{emqx_management_proto_v3,unsubscribe_batch,['Node','ClientId','Topics']},{emqx_mgmt,do_unsubscribe_batch,['ClientId','Topics']}}],casts => []},{emqx_node_rebalance,2} => #{calls => [{{emqx_node_rebalance_proto_v2,purge_sessions,['Nodes','Count']},{emqx_eviction_agent,purge_sessions,['Count']}},{{emqx_node_rebalance_proto_v2,disable_rebalance_agent,['Nodes','OwnerPid','Kind']},{emqx_node_rebalance_agent,disable,['OwnerPid','Kind']}},{{emqx_node_rebalance_proto_v2,enable_rebalance_agent,['Nodes','OwnerPid','Kind']},{emqx_node_rebalance_agent,enable,['OwnerPid','Kind']}},{{emqx_node_rebalance_proto_v2,disconnected_session_counts,['Nodes']},{emqx_node_rebalance,disconnected_session_count,[]}},{{emqx_node_rebalance_proto_v2,disable_rebalance_agent,['Nodes','OwnerPid']},{emqx_node_rebalance_agent,disable,['OwnerPid']}},{{emqx_node_rebalance_proto_v2,enable_rebalance_agent,['Nodes','OwnerPid']},{emqx_node_rebalance_agent,enable,['OwnerPid']}},{{emqx_node_rebalance_proto_v2,session_counts,['Nodes']},{emqx_node_rebalance,session_count,[]}},{{emqx_node_rebalance_proto_v2,connection_counts,['Nodes']},{emqx_node_rebalance,connection_count,[]}},{{emqx_node_rebalance_proto_v2,evict_sessions,['Nodes','Count','RecipientNodes','ConnState']},{emqx_eviction_agent,evict_sessions,['Count','RecipientNodes','ConnState']}},{{emqx_node_rebalance_proto_v2,evict_connections,['Nodes','Count']},{emqx_eviction_agent,evict_connections,['Count']}},{{emqx_node_rebalance_proto_v2,available_nodes,['Nodes']},{emqx_node_rebalance,is_node_available,[]}}],casts => []},{emqx,2} => #{calls => [{{emqx_proto_v2,delete_all_deactivated_alarms,['Node']},{emqx_alarm,delete_all_deactivated_alarms,[]}},{{emqx_proto_v2,deactivate_alarm,['Node','Name']},{emqx_alarm,deactivate,['Name']}},{{emqx_proto_v2,clean_pem_cache,['Node']},{ssl_pem_cache,clear,[]}},{{emqx_proto_v2,clean_authz_cache,['Node']},{emqx_authz_cache,drain_cache,[]}},{{emqx_proto_v2,clean_authz_cache,['Node','ClientId']},{emqx_authz_cache,drain_cache,['ClientId']}},{{emqx_proto_v2,get_metrics,['Node']},{emqx_metrics,all,[]}},{{emqx_proto_v2,get_stats,['Node']},{emqx_stats,getstats,[]}},{{emqx_proto_v2,get_alarms,['Node','Type']},{emqx_alarm,get_alarms,['Type']}},{{emqx_proto_v2,are_running,['Nodes']},{emqx,is_running,[]}},{{emqx_proto_v2,is_running,['Node']},{emqx,is_running,[]}}],casts => []},{emqx_shared_sub,1} => #{calls => [{{emqx_shared_sub_proto_v1,dispatch_with_ack,['Pid','Group','Topic','Msg','Timeout']},{emqx_shared_sub,do_dispatch_with_ack,['Pid','Group','Topic','Msg']}}],casts => [{{emqx_shared_sub_proto_v1,send,['Node','Pid','Topic','Msg']},{erlang,send,['Pid','Msg']}}]},{emqx_broker,1} => #{calls => [{{emqx_broker_proto_v1,list_subscriptions_via_topic,['Node','Topic']},{emqx_broker,subscriptions_via_topic,['Topic']}},{{emqx_broker_proto_v1,list_client_subscriptions,['Node','ClientId']},{emqx_broker,subscriptions,['ClientId']}},{{emqx_broker_proto_v1,forward,['Node','Topic','Delivery']},{emqx_broker,dispatch,['Topic','Delivery']}}],casts => [{{emqx_broker_proto_v1,forward_async,['Node','Topic','Delivery']},{emqx_broker,dispatch,['Topic','Delivery']}}]},{emqx_mgmt_trace,2} => #{calls => [{{emqx_mgmt_trace_proto_v2,read_trace_file,['Node','Name','Position','Limit']},{emqx_mgmt_api_trace,read_trace_file,['Name','Position','Limit']}},{{emqx_mgmt_trace_proto_v2,trace_file_detail,['Nodes','File']},{emqx_trace,trace_file_detail,['File']}},{{emqx_mgmt_trace_proto_v2,trace_file,['Nodes','File']},{emqx_trace,trace_file,['File']}},{{emqx_mgmt_trace_proto_v2,get_trace_size,['Nodes']},{emqx_mgmt_api_trace,get_trace_size,[]}}],casts => []},{emqx_ds,1} => #{calls => [{{emqx_ds_proto_v1,store_batch,['Node','DB','Shard','Batch','Options']},{emqx_ds_replication_layer,do_store_batch_v1,['DB','Shard','Batch','Options']}},{{emqx_ds_proto_v1,next,['Node','DB','Shard','Iter','BatchSize']},{emqx_ds_replication_layer,do_next_v1,['DB','Shard','Iter','BatchSize']}},{{emqx_ds_proto_v1,make_iterator,['Node','DB','Shard','Stream','TopicFilter','StartTime']},{emqx_ds_replication_layer,do_make_iterator_v1,['DB','Shard','Stream','TopicFilter','StartTime']}},{{emqx_ds_proto_v1,get_streams,['Node','DB','Shard','TopicFilter','Time']},{emqx_ds_replication_layer,do_get_streams_v1,['DB','Shard','TopicFilter','Time']}},{{emqx_ds_proto_v1,drop_db,['Node','DB']},{emqx_ds_replication_layer,do_drop_db_v1,['DB']}}],casts => []},{emqx_mgmt_api_plugins,2} => #{calls => [{{emqx_mgmt_api_plugins_proto_v2,ensure_action,['Name','Action']},{emqx_mgmt_api_plugins,ensure_action,['Name','Action']}},{{emqx_mgmt_api_plugins_proto_v2,delete_package,['Name']},{emqx_mgmt_api_plugins,delete_package,['Name']}},{{emqx_mgmt_api_plugins_proto_v2,describe_package,['Nodes','Name']},{emqx_mgmt_api_plugins,describe_package,['Name']}},{{emqx_mgmt_api_plugins_proto_v2,install_package,['Nodes','Filename','Bin']},{emqx_mgmt_api_plugins,install_package,['Filename','Bin']}},{{emqx_mgmt_api_plugins_proto_v2,get_plugins,['Nodes']},{emqx_mgmt_api_plugins,get_plugins,[]}}],casts => []},{emqx_gateway_http,1} => #{calls => [{{emqx_gateway_http_proto_v1,get_cluster_status,['Nodes','GwName']},{emqx_gateway_http,gateway_status,['GwName']}}],casts => []}},signatures => #{{emqx_eviction_agent,purge_sessions,1} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},{c,atom,[disabled],unknown}],{2,{c,atom,[error],unknown}}},none,none],unknown},[any]},{emqx_conf_proto_v2,update,3} => {any,[{c,list,{{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,nil,[],unknown}},nonempty},any,{c,map,{[{{c,atom,[lazy_evaluator],unknown},optional,{c,function,{{c,product,[{c,function,{any,any},unknown}],unknown},any},unknown}},{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_conf_proto_v3,get_hocon_config,2} => {any,[{c,atom,any,unknown},{c,binary,{8,0},unknown}]},{emqx_resource_proto_v1,remove,1} => {any,[{c,binary,{8,0},unknown}]},{emqx_management_proto_v2,list_subscriptions,1} => {any,[{c,atom,any,unknown}]},{emqx_node_rebalance_api_proto_v2,node_rebalance_purge_start,2} => {any,[{c,atom,any,unknown},{c,map,{[{{c,atom,[purge_rate],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}}],none,none},unknown}]},{emqx_node_rebalance_status,local_status,0} => {{c,union,[{c,atom,[disabled],unknown},none,none,none,none,none,{c,tuple_set,[{2,[{c,tuple,[{c,atom,[evacuation],unknown},any],{2,{c,atom,[evacuation],unknown}}},{c,tuple,[{c,atom,[purge],unknown},any],{2,{c,atom,[purge],unknown}}},{c,tuple,[{c,atom,[rebalance],unknown},{c,map,{[],{c,atom,[connection_eviction_rate,connection_goal,coordinator_node,disconnected_session_goal,recipients,session_eviction_rate,state,stats],unknown},any},unknown}],{2,{c,atom,[rebalance],unknown}}}]}],unknown},none,none],unknown},[]},{emqx_alarm,get_alarms,1} => {any,[{c,atom,[activated,all,deactivated],unknown}]},{emqx_exhook_mgr,all_servers_info,0} => {any,[]},{emqx_resource_proto_v1,create,5} => {any,[{c,binary,{8,0},unknown},{c,binary,{8,0},unknown},{c,atom,any,unknown},any,{c,map,{[{{c,atom,[auto_restart_interval],unknown},optional,{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,1,pos_inf},integer},none,none,none],unknown}},{{c,atom,[auto_retry_interval],unknown},optional,{c,number,any,integer}},{{c,atom,[batch_size],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[batch_time],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[health_check_interval],unknown},optional,{c,number,any,integer}},{{c,atom,[health_check_timeout],unknown},optional,{c,number,any,integer}},{{c,atom,[inflight_window],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[max_buffer_bytes],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[query_mode],unknown},optional,{c,atom,[async,no_queries,simple_async,simple_async_internal_buffer,simple_sync,simple_sync_internal_buffer,sync],unknown}},{{c,atom,[resume_interval],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[spawn_buffer_workers],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[start_after_created],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[start_timeout],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[wait_for_resource_ready],unknown},optional,{c,number,any,integer}},{{c,atom,[worker_pool_size],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}}],none,none},unknown}]},{emqx_conf_proto_v2,get_config,2} => {any,[{c,atom,any,unknown},{c,list,{{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,nil,[],unknown}},unknown}]},{emqx_management_proto_v2,node_info,1} => {any,[{c,atom,any,unknown}]},{emqx_delayed,get_delayed_message,1} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,atom,[not_found],unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,map,{[{{c,atom,[delayed_interval],unknown},mandatory,any},{{c,atom,[delayed_remaining],unknown},mandatory,{c,number,any,integer}},{{c,atom,[expected_at],unknown},mandatory,{c,binary,{8,0},unknown}},{{c,atom,[from_clientid],unknown},mandatory,{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}},{{c,atom,[from_username],unknown},mandatory,any},{{c,atom,[msgid],unknown},mandatory,{c,binary,{8,0},unknown}},{{c,atom,[node],unknown},mandatory,any},{{c,atom,[payload],unknown},optional,{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{any,{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},{c,number,{int_rng,0,255},integer},none,none,none],unknown},{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},none,none,none,none],unknown}},{{c,atom,[publish_at],unknown},mandatory,{c,binary,{8,0},unknown}},{{c,atom,[qos],unknown},mandatory,any},{{c,atom,[topic],unknown},mandatory,{c,binary,{8,0},unknown}}],none,none},unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},[any]},{emqx_gateway_cm,do_get_chan_info,3} => {{c,union,[{c,atom,[undefined],unknown},none,none,none,none,none,none,none,{c,map,{[{{c,atom,[node],unknown},mandatory,{c,atom,any,unknown}}],any,any},unknown}],unknown},[any,any,any]},{emqx_node_rebalance_evacuation,is_node_available,0} => {{c,atom,any,unknown},[]},{emqx_mgmt_data_backup,list_files,0} => {{c,list,{any,{c,nil,[],unknown}},unknown},[]},{emqx_cm,do_get_chann_conn_mod,2} => {any,[any,any]},{emqx_broker_proto_v1,forward,3} => {any,[{c,atom,any,unknown},{c,binary,{8,0},unknown},{c,tuple,[{c,atom,[delivery],unknown},{c,identifier,[pid],unknown},{c,tuple,[{c,atom,[message],unknown},{c,binary,{8,0},unknown},any,{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,map,{[],{c,atom,any,unknown},{c,atom,[false,true],unknown}},unknown},{c,map,{[{{c,atom,[allow_publish],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[peerhost],unknown},optional,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown}},{{c,atom,[properties],unknown},optional,{c,map,{[],{c,atom,any,unknown},any},unknown}},{{c,atom,[proto_ver],unknown},optional,{c,union,[none,{c,binary,{8,0},unknown},none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none],unknown}},{{c,atom,[protocol],unknown},optional,{c,atom,any,unknown}},{{c,atom,[username],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}}],{c,atom,any,unknown},any},unknown},{c,binary,{8,0},unknown},{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{any,{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},{c,number,{int_rng,0,255},integer},none,none,none],unknown},{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},none,none,none,none],unknown},{c,number,any,integer},any],{10,{c,atom,[message],unknown}}}],{3,{c,atom,[delivery],unknown}}}]},{emqx_dashboard_proto_v1,do_sample,2} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,1,pos_inf},integer},none,none,none],unknown}]},{emqx_node_rebalance,start,1} => {any,[{c,map,{[],any,any},unknown}]},{emqx_node_rebalance_proto_v2,session_counts,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_ft_storage_fs_proxy,lookup_local_assembler,1} => {any,[any]},{emqx_gateway_cm,do_set_chan_stats,4} => {{c,atom,[false,true],unknown},[any,any,any,any]},{emqx_delayed_proto_v2,get_delayed_message,2} => {any,[{c,atom,any,unknown},{c,binary,{8,0},unknown}]},{emqx_gateway_cm,do_cast,4} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown},any]},{emqx_management_proto_v4,call_client,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},any]},{emqx_prometheus_proto_v1,stop,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_node_rebalance_api_proto_v1,node_rebalance_start,2} => {any,[{c,atom,any,unknown},{c,map,{[{{c,atom,[abs_conn_threshold],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[abs_sess_threshold],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[conn_evict_rate],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[nodes],unknown},optional,{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}},{{c,atom,[rel_conn_threshold],unknown},optional,{c,number,any,unknown}},{{c,atom,[rel_sess_threshold],unknown},optional,{c,number,any,unknown}},{{c,atom,[sess_evict_rate],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[wait_health_check],unknown},optional,{c,number,any,unknown}},{{c,atom,[wait_takeover],unknown},optional,{c,number,any,unknown}}],none,none},unknown}]},{ssl_pem_cache,clear,0} => {any,[]},{emqx_conf_proto_v3,update,4} => {any,[{c,atom,any,unknown},{c,list,{{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,nil,[],unknown}},nonempty},any,{c,map,{[{{c,atom,[lazy_evaluator],unknown},optional,{c,function,{{c,product,[{c,function,{any,any},unknown}],unknown},any},unknown}},{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_mgmt_data_backup,maybe_copy_and_import,2} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[bardrpc],unknown},any],{2,{c,atom,[bardrpc],unknown}}},{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,map,{[{{c,atom,[config_errors],unknown},mandatory,{c,map,{[],{c,list,{any,{c,nil,[],unknown}},unknown},{c,tuple,[any,any],{2,any}}},unknown}},{{c,atom,[db_errors],unknown},mandatory,{c,map,{[],{c,atom,any,unknown},{c,tuple,[any,any],{2,any}}},unknown}}],none,none},unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},[any,{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_conf_proto_v2,get_all,1} => {any,[{c,list,{{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,nil,[],unknown}},unknown}]},{emqx_management_proto_v4,unsubscribe,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,binary,{8,0},unknown}]},{emqx,is_running,0} => {{c,atom,[false,true],unknown},[]},{emqx_cm,do_get_chan_stats,2} => {any,[any,any]},{emqx_rule_engine_proto_v1,reset_metrics,1} => {any,[{c,binary,{8,0},unknown}]},{emqx_resource,create_local,5} => {{c,tuple,[{c,atom,[ok],unknown},{c,map,{[{{c,atom,[added_channels],unknown},mandatory,any},{{c,atom,[callback_mode],unknown},mandatory,{c,atom,[always_sync,async_if_possible],unknown}},{{c,atom,[config],unknown},mandatory,any},{{c,atom,[error],unknown},mandatory,any},{{c,atom,[id],unknown},mandatory,{c,binary,{8,0},unknown}},{{c,atom,[mod],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[query_mode],unknown},mandatory,{c,atom,[async,no_queries,simple_async,simple_async_internal_buffer,simple_sync,simple_sync_internal_buffer,sync],unknown}},{{c,atom,[state],unknown},mandatory,any},{{c,atom,[status],unknown},mandatory,{c,atom,[connected,connecting,disconnected,stopped],unknown}}],none,none},unknown}],{2,{c,atom,[ok],unknown}}},[{c,binary,{8,0},unknown},{c,binary,{8,0},unknown},{c,atom,any,unknown},any,{c,map,{[{{c,atom,[auto_restart_interval],unknown},optional,{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,1,pos_inf},integer},none,none,none],unknown}},{{c,atom,[auto_retry_interval],unknown},optional,{c,number,any,integer}},{{c,atom,[batch_size],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[batch_time],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[health_check_interval],unknown},optional,{c,number,any,integer}},{{c,atom,[health_check_timeout],unknown},optional,{c,number,any,integer}},{{c,atom,[inflight_window],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[max_buffer_bytes],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[query_mode],unknown},optional,{c,atom,[async,no_queries,simple_async,simple_async_internal_buffer,simple_sync,simple_sync_internal_buffer,sync],unknown}},{{c,atom,[resume_interval],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[spawn_buffer_workers],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[start_after_created],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[start_timeout],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[wait_for_resource_ready],unknown},optional,{c,number,any,integer}},{{c,atom,[worker_pool_size],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}}],none,none},unknown}]},{emqx_gateway_cm,do_set_chan_info,4} => {{c,atom,[false,true],unknown},[any,any,any,any]},{emqx_dashboard_monitor,current_rate,1} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[badrpc],unknown},any],{2,{c,atom,[badrpc],unknown}}},{c,tuple,[{c,atom,[ok],unknown},any],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,atom,any,unknown}]},{emqx_management_proto_v4,get_full_config,1} => {any,[{c,atom,any,unknown}]},{emqx_gateway_cm_proto_v1,takeover_session,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_proto_v2,are_running,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{erlang,send,2} => {any,[any,any]},{emqx_proto_v2,get_stats,1} => {any,[{c,atom,any,unknown}]},{emqx_plugins_proto_v1,get_tar,3} => {any,[{c,atom,any,unknown},{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none],unknown}]},{emqx_gateway_cm_proto_v1,lookup_by_clientid,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}]},{emqx_ft_storage_fs_reader_proto_v1,read,3} => {any,[{c,atom,any,unknown},{c,identifier,[pid],unknown},{c,number,{int_rng,1,pos_inf},integer}]},{emqx_mgmt_data_backup_proto_v1,list_files,2} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none],unknown}]},{emqx_bridge_api,lookup_from_local_node,2} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,atom,[not_bridge_v1_compatible,not_found],unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},any],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_connector_proto_v1,lookup_from_all_nodes,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_node_rebalance_proto_v1,enable_rebalance_agent,2} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,identifier,[pid],unknown}]},{emqx_node_rebalance_proto_v2,evict_sessions,4} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,number,{int_rng,0,pos_inf},integer},{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,atom,[connected,connecting,disconnected,idle,reauthenticating],unknown}]},{emqx_ds_replication_layer,do_drop_db_v1,1} => {{c,atom,[ok],unknown},[{c,atom,any,unknown}]},{emqx_gateway_api_listeners_proto_v1,listeners_cluster_status,2} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,list,{any,{c,nil,[],unknown}},unknown}]},{emqx_node_rebalance_status_proto_v1,local_status,1} => {any,[{c,atom,any,unknown}]},{emqx_proto_v2,get_alarms,2} => {any,[{c,atom,any,unknown},{c,atom,[activated,all,deactivated],unknown}]},{emqx_node_rebalance_proto_v2,connection_counts,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_node_rebalance_proto_v2,evict_connections,2} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,number,{int_rng,0,pos_inf},integer}]},{emqx_mgmt_trace_proto_v1,trace_file,2} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,union,[{c,atom,any,unknown},none,none,none,{c,list,{any,{c,nil,[],unknown}},unknown},{c,number,{int_rng,0,1114111},integer},none,none,none],unknown},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_gateway_cm_proto_v1,get_chann_conn_mod,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_ft_storage_exporter_fs_proto_v1,list_exports,2} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,map,{[{{c,atom,[following],unknown},optional,any},{{c,atom,[limit],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[transfer],unknown},optional,{c,tuple,[{c,binary,{8,0},unknown},{c,binary,{8,0},unknown}],{2,any}}}],none,none},unknown}]},{emqx_node_rebalance_evacuation_proto_v1,available_nodes,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_gateway_cm_proto_v1,set_chan_info,4} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown},{c,map,{[],{c,atom,any,unknown},any},unknown}]},{emqx_resource_proto_v1,recreate,4} => {any,[{c,binary,{8,0},unknown},{c,atom,any,unknown},any,{c,map,{[{{c,atom,[auto_restart_interval],unknown},optional,{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,1,pos_inf},integer},none,none,none],unknown}},{{c,atom,[auto_retry_interval],unknown},optional,{c,number,any,integer}},{{c,atom,[batch_size],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[batch_time],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[health_check_interval],unknown},optional,{c,number,any,integer}},{{c,atom,[health_check_timeout],unknown},optional,{c,number,any,integer}},{{c,atom,[inflight_window],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[max_buffer_bytes],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[query_mode],unknown},optional,{c,atom,[async,no_queries,simple_async,simple_async_internal_buffer,simple_sync,simple_sync_internal_buffer,sync],unknown}},{{c,atom,[resume_interval],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[spawn_buffer_workers],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[start_after_created],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[start_timeout],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[wait_for_resource_ready],unknown},optional,{c,number,any,integer}},{{c,atom,[worker_pool_size],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}}],none,none},unknown}]},{emqx_mgmt,do_subscribe,2} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,atom,[channel_not_found],unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[subscribe],unknown},any],{2,{c,atom,[subscribe],unknown}}}]}],unknown},[any,any]},{emqx_bridge_proto_v3,list_bridges_on_nodes,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_gateway_cm,do_get_chan_stats,3} => {any,[any,any,any]},{emqx_proto_v2,delete_all_deactivated_alarms,1} => {any,[{c,atom,any,unknown}]},{emqx_mgmt_api_plugins_proto_v1,install_package,2} => {any,[{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,binary,{8,0},unknown}]},{emqx_bridge_resource,stop,2} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},none,none],unknown},[any,{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{any,{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},{c,number,{int_rng,0,255},integer},none,none,none],unknown},{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},none,none,none,none],unknown}]},{emqx_cm_proto_v1,takeover_session,2} => {any,[{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_authz_cache,drain_cache,1} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},{c,atom,[not_found],unknown}],{2,{c,atom,[error],unknown}}},none,none],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}]},{emqx_alarm,deactivate,1} => {any,[any]},{emqx_retainer_dispatcher,wait_dispatch_complete,1} => {{c,atom,[ok],unknown},[any]},{emqx_metrics_proto_v1,get_metrics,4} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none],unknown}]},{emqx_conf_proto_v2,get_override_config_file,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_mgmt_api_plugins_proto_v1,delete_package,1} => {any,[{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_node_rebalance_api_proto_v1,node_rebalance_stop,1} => {any,[{c,atom,any,unknown}]},{emqx_conf_proto_v3,get_config,2} => {any,[{c,atom,any,unknown},{c,list,{{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,nil,[],unknown}},unknown}]},{emqx_delayed_proto_v1,delete_delayed_message,2} => {any,[{c,atom,any,unknown},{c,binary,{8,0},unknown}]},{emqx_gateway_cm,do_call,5} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown},any,any]},{emqx_eviction_agent_proto_v2,evict_session_channel,4} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,map,{[{{c,atom,[clean_start],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[clientid],unknown},optional,{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}},{{c,atom,[conn_mod],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[conn_props],unknown},optional,{c,map,{[],{c,atom,any,unknown},any},unknown}},{{c,atom,[connected],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[connected_at],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[disconnected_at],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[expiry_interval],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[keepalive],unknown},optional,{c,number,{int_rng,0,1114111},integer}},{{c,atom,[peercert],unknown},optional,{c,union,[{c,atom,[nossl,undefined],unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,union,[{c,atom,any,unknown},none,none,none,none,none,{c,tuple,any,{any,any}},none,none],unknown},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}},{{c,atom,[peername],unknown},mandatory,{c,tuple,[{c,union,[{c,atom,[local,undefined,unspec],unknown},none,none,none,none,none,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown},none,none],unknown},any],{2,any}}},{{c,atom,[proto_name],unknown},optional,{c,binary,{8,0},unknown}},{{c,atom,[proto_ver],unknown},optional,{c,union,[none,{c,binary,{8,0},unknown},none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none],unknown}},{{c,atom,[receive_maximum],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[sockname],unknown},mandatory,{c,tuple,[{c,union,[{c,atom,[local,undefined,unspec],unknown},none,none,none,none,none,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown},none,none],unknown},any],{2,any}}},{{c,atom,[socktype],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[username],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}}],{c,atom,any,unknown},any},unknown},{c,map,{[{{c,atom,[anonymous],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[auth_result],unknown},optional,{c,atom,[bad_authentication_method,bad_clientid_or_password,bad_username_or_password,banned,client_identifier_not_valid,not_authorized,server_busy,server_unavailable,success],unknown}},{{c,atom,[clientid],unknown},mandatory,{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}},{{c,atom,[cn],unknown},optional,{c,binary,{8,0},unknown}},{{c,atom,[dn],unknown},optional,{c,binary,{8,0},unknown}},{{c,atom,[is_bridge],unknown},mandatory,{c,atom,[false,true],unknown}},{{c,atom,[is_superuser],unknown},mandatory,{c,atom,[false,true],unknown}},{{c,atom,[mountpoint],unknown},mandatory,{c,union,[{c,atom,[undefined],unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}},{{c,atom,[password],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}},{{c,atom,[peerhost],unknown},mandatory,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown}},{{c,atom,[protocol],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[sockport],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[username],unknown},mandatory,{c,union,[{c,atom,[undefined],unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}},{{c,atom,[ws_cookie],unknown},optional,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,{any,{c,nil,[],unknown}},unknown},none,none,none,none],unknown}},{{c,atom,[zone],unknown},mandatory,{c,atom,any,unknown}}],{c,atom,any,unknown},any},unknown}]},{emqx_bridge_proto_v5,stop_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_node_rebalance,is_node_available,0} => {{c,atom,any,unknown},[]},{emqx_node_rebalance_proto_v2,available_nodes,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_persistent_session_ds,do_ensure_iterator_closed,1} => {{c,atom,[ok],unknown},[any]},{emqx_slow_subs_proto_v1,get_history,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_node_rebalance_proto_v2,disable_rebalance_agent,2} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,identifier,[pid],unknown}]},{emqx_conf_proto_v3,get_config,3} => {any,[{c,atom,any,unknown},{c,list,{{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,nil,[],unknown}},unknown},any]},{emqx_bridge_proto_v3,start_bridges_to_all_nodes,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_node_rebalance_purge_proto_v1,stop,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_node_rebalance_proto_v2,purge_sessions,2} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,number,{int_rng,0,pos_inf},integer}]},{emqx_mgmt,do_unsubscribe,2} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,atom,[channel_not_found],unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[unsubscribe],unknown},{c,list,{{c,tuple,[{c,union,[none,{c,binary,{8,0},unknown},none,none,none,none,{c,tuple,[any,any,any],{3,any}},none,none],unknown},{c,map,{[],any,any},unknown}],{2,any}},{c,nil,[],unknown}},nonempty}],{2,{c,atom,[unsubscribe],unknown}}}]}],unknown},[any,any]},{emqx_node_rebalance_agent,enable,2} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},{c,atom,[eviction_agent_busy,invalid_coordinator],unknown}],{2,{c,atom,[error],unknown}}},none,none],unknown},[{c,identifier,[pid],unknown},any]},{emqx_eviction_agent,evict_session_channel,3} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,union,[{c,atom,[undefined],unknown},none,none,{c,identifier,[pid],unknown},none,none,none,none,none],unknown}],{2,{c,atom,[ok],unknown}}}]},{3,[{c,tuple,[{c,atom,[ok],unknown},{c,union,[{c,atom,[undefined],unknown},none,none,{c,identifier,[pid],unknown},none,none,none,none,none],unknown},any],{3,{c,atom,[ok],unknown}}}]}],unknown},[any,{c,map,{[{{c,atom,[clean_start],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[clientid],unknown},optional,{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}},{{c,atom,[conn_mod],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[conn_props],unknown},optional,{c,map,{[],{c,atom,any,unknown},any},unknown}},{{c,atom,[connected],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[connected_at],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[disconnected_at],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[expiry_interval],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[keepalive],unknown},optional,{c,number,{int_rng,0,1114111},integer}},{{c,atom,[peercert],unknown},optional,{c,union,[{c,atom,[nossl,undefined],unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,union,[{c,atom,any,unknown},none,none,none,none,none,{c,tuple,any,{any,any}},none,none],unknown},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}},{{c,atom,[peername],unknown},mandatory,{c,tuple,[{c,union,[{c,atom,[local,undefined,unspec],unknown},none,none,none,none,none,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown},none,none],unknown},any],{2,any}}},{{c,atom,[proto_name],unknown},optional,{c,binary,{8,0},unknown}},{{c,atom,[proto_ver],unknown},optional,{c,union,[none,{c,binary,{8,0},unknown},none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none],unknown}},{{c,atom,[receive_maximum],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[sockname],unknown},mandatory,{c,tuple,[{c,union,[{c,atom,[local,undefined,unspec],unknown},none,none,none,none,none,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown},none,none],unknown},any],{2,any}}},{{c,atom,[socktype],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[username],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}}],{c,atom,any,unknown},any},unknown},{c,map,{[{{c,atom,[anonymous],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[auth_result],unknown},optional,{c,atom,[bad_authentication_method,bad_clientid_or_password,bad_username_or_password,banned,client_identifier_not_valid,not_authorized,server_busy,server_unavailable,success],unknown}},{{c,atom,[clientid],unknown},mandatory,{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}},{{c,atom,[cn],unknown},optional,{c,binary,{8,0},unknown}},{{c,atom,[dn],unknown},optional,{c,binary,{8,0},unknown}},{{c,atom,[is_bridge],unknown},mandatory,{c,atom,[false,true],unknown}},{{c,atom,[is_superuser],unknown},mandatory,{c,atom,[false,true],unknown}},{{c,atom,[mountpoint],unknown},mandatory,{c,union,[{c,atom,[undefined],unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}},{{c,atom,[password],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}},{{c,atom,[peerhost],unknown},mandatory,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown}},{{c,atom,[protocol],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[sockport],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[username],unknown},mandatory,{c,union,[{c,atom,[undefined],unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}},{{c,atom,[ws_cookie],unknown},optional,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,{any,{c,nil,[],unknown}},unknown},none,none,none,none],unknown}},{{c,atom,[zone],unknown},mandatory,{c,atom,any,unknown}}],{c,atom,any,unknown},any},unknown}]},{emqx_mgmt_trace_proto_v2,trace_file,2} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,union,[{c,atom,any,unknown},none,none,none,{c,list,{any,{c,nil,[],unknown}},unknown},{c,number,{int_rng,0,1114111},integer},none,none,none],unknown},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_management_proto_v4,broker_info,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_eviction_agent_proto_v2,all_channels_count,2} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none],unknown}]},{emqx_bridge_proto_v5,v2_list_bridges_on_nodes,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_cm,do_get_chan_info,2} => {any,[any,any]},{emqx_conf_proto_v1,remove_config,2} => {any,[{c,list,{{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,nil,[],unknown}},nonempty},{c,map,{[{{c,atom,[lazy_evaluator],unknown},optional,{c,function,{{c,product,[{c,function,{any,any},unknown}],unknown},any},unknown}},{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_telemetry,get_cluster_uuid,0} => {any,[]},{emqx_mgmt_trace_proto_v1,get_trace_size,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_gateway_api_listeners,do_listeners_cluster_status,1} => {{c,map,{[],any,any},unknown},[{c,list,{any,{c,nil,[],unknown}},unknown}]},{emqx_prometheus,do_stop,0} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},{c,atom,[not_found,restarting,running,simple_one_for_one],unknown}],{2,{c,atom,[error],unknown}}},none,none],unknown},[]},{emqx_node_rebalance_status_proto_v2,local_status,1} => {any,[{c,atom,any,unknown}]},{emqx_gateway_cm,do_takeover_session,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_proto_v2,clean_pem_cache,1} => {any,[{c,atom,any,unknown}]},{emqx_bridge_proto_v5,list_bridges_on_nodes,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_resource_proto_v1,reset_metrics,1} => {any,[{c,binary,{8,0},unknown}]},{emqx_telemetry,get_node_uuid,0} => {any,[]},{emqx_mgmt_api_plugins_proto_v1,ensure_action,2} => {any,[{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,atom,[restart,start,stop],unknown}]},{emqx_mgmt_api_listeners,do_list_listeners,0} => {{c,map,{[],{c,binary,{40,32},unknown},{c,union,[{c,atom,any,unknown},none,none,none,{c,list,{{c,map,{[],any,any},unknown},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}},unknown},[]},{emqx_bridge_proto_v2,list_bridges,1} => {any,[{c,atom,any,unknown}]},{emqx_node_rebalance_agent,enable,1} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},{c,atom,[eviction_agent_busy,invalid_coordinator],unknown}],{2,{c,atom,[error],unknown}}},none,none],unknown},[{c,identifier,[pid],unknown}]},{emqx_gateway_http,gateway_status,1} => {{c,map,{[{{c,atom,[current_connections],unknown},optional,any},{{c,atom,[max_connections],unknown},optional,{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none],unknown}},{{c,atom,[node],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[status],unknown},mandatory,{c,atom,[running,stopped,unloaded],unknown}}],none,none},unknown},[{c,atom,any,unknown}]},{emqx_management_proto_v4,unsubscribe_batch,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,list,{{c,binary,{8,0},unknown},{c,nil,[],unknown}},unknown}]},{emqx_cm,kick_session,1} => {{c,atom,[ok],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}]},{emqx_mgmt,broker_info,0} => {{c,map,{[{{c,atom,[node],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[node_status],unknown},mandatory,{c,atom,[running],unknown}},{{c,atom,[otp_release],unknown},mandatory,{c,binary,{8,0},unknown}}],any,any},unknown},[]},{emqx_resource,create_dry_run_local,2} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},none,none],unknown},[{c,atom,any,unknown},any]},{emqx_management_proto_v1,unsubscribe,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,binary,{8,0},unknown}]},{emqx_ds_proto_v1,make_iterator,6} => {any,[{c,atom,any,unknown},{c,atom,any,unknown},{c,binary,{8,0},unknown},{c,opaque,[{opaque,emqx_ds_storage_layer,stream,0,{c,map,{[{{c,number,{int_set,[1]},integer},mandatory,{c,number,{int_set,[1]},integer}},{{c,number,{int_set,[2]},integer},mandatory,{c,number,{int_rng,0,1114111},integer}},{{c,number,{int_set,[3]},integer},mandatory,any}],none,none},unknown}}],unknown},{c,list,{{c,union,[{c,atom,['','#','+'],unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,nil,[],unknown}},unknown},{c,number,{int_rng,0,pos_inf},integer}]},{emqx_topic_metrics_proto_v1,metrics,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_management_proto_v1,node_info,1} => {any,[{c,atom,any,unknown}]},{emqx_ft_storage_fs_proto_v1,pread,5} => {any,[{c,atom,any,unknown},{c,tuple,[{c,binary,{8,0},unknown},{c,binary,{8,0},unknown}],{2,any}},{c,map,{[{{c,atom,[fragment],unknown},mandatory,{c,tuple_set,[{2,[{c,tuple,[{c,atom,[filemeta],unknown},{c,map,{[{{c,atom,[checksum],unknown},optional,{c,tuple,[{c,atom,any,unknown},{c,binary,{8,0},unknown}],{2,any}}},{{c,atom,[expire_at],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[name],unknown},mandatory,{c,list,{{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}},unknown}},{{c,atom,[segments_ttl],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[size],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[user_data],unknown},optional,{c,union,[{c,atom,[false,null,true],unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,union,[{c,atom,[false,null,true],unknown},{c,binary,{8,0},unknown},none,none,{c,list,{any,{c,nil,[],unknown}},unknown},{c,number,any,unknown},none,none,{c,map,{[],{c,binary,{8,0},unknown},any},unknown}],unknown},{c,nil,[],unknown}},unknown},{c,number,any,unknown},none,none,{c,map,{[],{c,binary,{8,0},unknown},{c,union,[{c,atom,[false,null,true],unknown},{c,binary,{8,0},unknown},none,none,{c,list,{any,{c,nil,[],unknown}},unknown},{c,number,any,unknown},none,none,{c,map,{[],{c,binary,{8,0},unknown},any},unknown}],unknown}},unknown}],unknown}}],none,none},unknown}],{2,{c,atom,[filemeta],unknown}}},{c,tuple,[{c,atom,[segment],unknown},{c,map,{[{{c,atom,[offset],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[size],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}}],none,none},unknown}],{2,{c,atom,[segment],unknown}}}]}],unknown}},{{c,atom,[path],unknown},mandatory,{c,union,[{c,atom,any,unknown},none,none,none,{c,list,{{c,union,[{c,atom,any,unknown},none,none,none,{c,list,{any,{c,nil,[],unknown}},unknown},{c,number,{int_rng,0,1114111},integer},none,none,none],unknown},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}},{{c,atom,[size],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[timestamp],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}}],none,none},unknown},{c,number,{int_rng,0,pos_inf},integer},{c,number,{int_rng,0,pos_inf},integer}]},{emqx_node_rebalance_status_proto_v1,rebalance_status,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_bridge_proto_v4,start_bridges_to_all_nodes,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_proto_v2,clean_authz_cache,1} => {any,[{c,atom,any,unknown}]},{emqx_cm,do_kick_session,3} => {{c,atom,[ok],unknown},[any,{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_mgmt_api_plugins_proto_v2,ensure_action,2} => {any,[{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,atom,[restart,start,stop],unknown}]},{emqx_conf_proto_v3,get_hocon_config,1} => {any,[{c,atom,any,unknown}]},{emqx_node_rebalance_api_proto_v2,node_rebalance_evacuation_stop,1} => {any,[{c,atom,any,unknown}]},{emqx_node_rebalance_purge,start,1} => {any,[{c,map,{[],any,any},unknown}]},{emqx_resource_proto_v1,create_dry_run,2} => {any,[{c,atom,any,unknown},any]},{emqx_cm_proto_v2,get_chan_info,2} => {any,[{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_exhook_proto_v1,server_hooks_metrics,2} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,binary,{8,0},unknown}]},{emqx_mgmt_api_plugins,get_plugins,0} => {{c,tuple,[{c,atom,any,unknown},{c,list,{{c,map,{[],any,any},unknown},{c,nil,[],unknown}},unknown}],{2,any}},[]},{emqx_bridge_proto_v2,lookup_from_all_nodes,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_management_proto_v3,subscribe,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,list,{{c,tuple,[{c,binary,{8,0},unknown},{c,map,{[{{c,atom,[nl],unknown},mandatory,{c,number,{int_set,[0,1]},integer}},{{c,atom,[qos],unknown},mandatory,{c,number,{int_set,[0,1,2]},integer}},{{c,atom,[rap],unknown},mandatory,{c,number,{int_set,[0,1]},integer}},{{c,atom,[rh],unknown},mandatory,{c,number,{int_set,[0,1,2]},integer}}],{c,atom,any,unknown},any},unknown}],{2,any}},{c,nil,[],unknown}},unknown}]},{emqx_management_proto_v2,list_listeners,1} => {any,[{c,atom,any,unknown}]},{emqx_cm_proto_v2,takeover_finish,2} => {any,[{c,atom,any,unknown},{c,identifier,[pid],unknown}]},{emqx_connector_proto_v1,list_connectors_on_nodes,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_metrics,all,0} => {{c,list,{{c,tuple,[any,{c,number,any,integer}],{2,any}},{c,nil,[],unknown}},unknown},[]},{emqx_gateway_cm,do_kick_session,4} => {{c,atom,[ok],unknown},[{c,atom,any,unknown},any,{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_node_rebalance_api_proto_v2,node_rebalance_stop,1} => {any,[{c,atom,any,unknown}]},{emqx_node_rebalance_proto_v3,disable_rebalance_agent,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,identifier,[pid],unknown},any]},{emqx_node_rebalance_agent,disable,2} => {any,[any,any]},{emqx_mgmt_data_backup_proto_v1,import_file,4} => {any,[{c,atom,any,unknown},{c,atom,any,unknown},{c,binary,{8,0},unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none],unknown}]},{emqx_cm_proto_v2,takeover_session,2} => {any,[{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_delayed_proto_v2,clear_all,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_cm_proto_v2,kick_session,3} => {any,[{c,atom,[discard,kick],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_node_rebalance_api_proto_v2,node_rebalance_evacuation_start,2} => {any,[{c,atom,any,unknown},{c,map,{[{{c,atom,[conn_evict_rate],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[migrate_to],unknown},optional,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}},{{c,atom,[server_reference],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}},{{c,atom,[sess_evict_rate],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[wait_health_check],unknown},optional,{c,number,any,unknown}},{{c,atom,[wait_takeover],unknown},optional,{c,number,any,unknown}}],none,none},unknown}]},{emqx_proto_v1,delete_all_deactivated_alarms,1} => {any,[{c,atom,any,unknown}]},{emqx_mgmt_trace_proto_v2,read_trace_file,4} => {any,[{c,atom,any,unknown},{c,binary,{8,0},unknown},{c,number,{int_rng,0,pos_inf},integer},{c,number,{int_rng,0,pos_inf},integer}]},{emqx_gateway_cm,do_call,4} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown},any]},{emqx_proto_v2,get_metrics,1} => {any,[{c,atom,any,unknown}]},{emqx_cm_proto_v2,get_chan_stats,2} => {any,[{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_node_rebalance,connection_count,0} => {{c,tuple,[{c,atom,[ok],unknown},any],{2,{c,atom,[ok],unknown}}},[]},{emqx_authn_proto_v1,lookup_from_all_nodes,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,atom,any,unknown},{c,binary,{8,0},unknown}]},{emqx_node_rebalance_status_proto_v2,rebalance_status,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx,get_config,2} => {any,[any,any]},{emqx_bridge_proto_v3,stop_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_retainer_proto_v1,wait_dispatch_complete,2} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none],unknown}]},{emqx_bridge_proto_v4,start_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_bridge_proto_v5,stop_bridges_to_all_nodes,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_shared_sub,do_dispatch_with_ack,4} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},none,none],unknown},[{c,identifier,[pid,port],unknown},any,any,{c,tuple,[{c,atom,[message],unknown},{c,binary,{8,0},unknown},any,{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,map,{[],{c,atom,any,unknown},{c,atom,[false,true],unknown}},unknown},{c,map,{[{{c,atom,[allow_publish],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[peerhost],unknown},optional,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown}},{{c,atom,[properties],unknown},optional,{c,map,{[],{c,atom,any,unknown},any},unknown}},{{c,atom,[proto_ver],unknown},optional,{c,union,[none,{c,binary,{8,0},unknown},none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none],unknown}},{{c,atom,[protocol],unknown},optional,{c,atom,any,unknown}},{{c,atom,[username],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}}],{c,atom,any,unknown},any},unknown},{c,binary,{8,0},unknown},{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{any,{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},{c,number,{int_rng,0,255},integer},none,none,none],unknown},{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},none,none,none,none],unknown},{c,number,any,integer},any],{10,{c,atom,[message],unknown}}}]},{emqx_bridge_proto_v4,restart_bridges_to_all_nodes,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_slow_subs,clear_history,0} => {any,[]},{emqx_retainer_mnesia,active_indices,0} => {{c,tuple,[any,any],{2,any}},[]},{emqx_conf_proto_v3,reset,3} => {any,[{c,atom,any,unknown},{c,list,{{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,nil,[],unknown}},nonempty},{c,map,{[{{c,atom,[lazy_evaluator],unknown},optional,{c,function,{{c,product,[{c,function,{any,any},unknown}],unknown},any},unknown}},{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_mgmt_api_plugins_proto_v2,describe_package,2} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_stats,getstats,0} => {{c,list,{{c,tuple,any,{any,any}},{c,nil,[],unknown}},unknown},[]},{emqx_mgmt_api_plugins,describe_package,1} => {{c,tuple,[{c,atom,any,unknown},{c,list,{{c,map,{[],any,any},unknown},{c,nil,[],unknown}},unknown}],{2,any}},[{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_management_proto_v1,call_client,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},any]},{emqx_conf_proto_v3,sync_data_from_node,1} => {any,[{c,atom,any,unknown}]},{emqx_bridge_v2_api,get_metrics_from_local_node,2} => {{c,map,{[{{c,atom,[dropped],unknown},mandatory,{c,number,any,integer}},{{c,atom,['dropped.expired'],unknown},mandatory,{c,number,any,integer}},{{c,atom,['dropped.other'],unknown},mandatory,{c,number,any,integer}},{{c,atom,['dropped.queue_full'],unknown},mandatory,{c,number,any,integer}},{{c,atom,['dropped.resource_not_found'],unknown},mandatory,{c,number,any,integer}},{{c,atom,['dropped.resource_stopped'],unknown},mandatory,{c,number,any,integer}},{{c,atom,[failed],unknown},mandatory,{c,number,any,integer}},{{c,atom,[inflight],unknown},mandatory,any},{{c,atom,[late_reply],unknown},mandatory,{c,number,any,integer}},{{c,atom,[matched],unknown},mandatory,{c,number,any,integer}},{{c,atom,[queuing],unknown},mandatory,any},{{c,atom,[rate],unknown},mandatory,any},{{c,atom,[rate_last5m],unknown},mandatory,any},{{c,atom,[rate_max],unknown},mandatory,any},{{c,atom,[received],unknown},mandatory,{c,number,any,integer}},{{c,atom,[retried],unknown},mandatory,{c,number,any,integer}},{{c,atom,[success],unknown},mandatory,{c,number,any,integer}}],none,none},unknown},[{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_node_rebalance_proto_v3,purge_sessions,2} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,number,{int_rng,0,pos_inf},integer}]},{emqx_resource,remove_local,1} => {{c,atom,[ok],unknown},[{c,binary,{8,0},unknown}]},{emqx_node_rebalance_proto_v3,enable_rebalance_agent,2} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,identifier,[pid],unknown}]},{emqx_node_rebalance_status,evacuation_status,0} => {{c,tuple,[{c,atom,any,unknown},{c,union,[{c,atom,[disabled],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[enabled],unknown},{c,map,{[{{c,atom,[conn_evict_rate],unknown},mandatory,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[current_conns],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[current_sessions],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[initial_conns],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[initial_sessions],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[migrate_to],unknown},mandatory,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,{any,{c,nil,[],unknown}},unknown},none,none,none,none],unknown}},{{c,atom,[server_reference],unknown},mandatory,{c,union,[{c,atom,[undefined],unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}},{{c,atom,[sess_evict_rate],unknown},mandatory,{c,number,{int_rng,1,pos_inf},integer}}],none,none},unknown}],{2,{c,atom,[enabled],unknown}}},none,none],unknown}],{2,any}},[]},{emqx_bridge_proto_v5,lookup_from_all_nodes,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_gateway_cm_proto_v1,get_chan_stats,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_cm_proto_v1,get_chan_stats,2} => {any,[{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_broker_proto_v1,list_client_subscriptions,2} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}]},{emqx_conf_cli,get_config,0} => {{c,map,{[],any,any},unknown},[]},{emqx_proto_v1,deactivate_alarm,2} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}]},{emqx_conf_proto_v3,update,3} => {any,[{c,list,{{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,nil,[],unknown}},nonempty},any,{c,map,{[{{c,atom,[lazy_evaluator],unknown},optional,{c,function,{{c,product,[{c,function,{any,any},unknown}],unknown},any},unknown}},{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_bridge_proto_v5,start_bridges_to_all_nodes,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_dashboard_monitor,do_sample,2} => {any,[{c,atom,any,unknown},any]},{emqx_management_proto_v3,list_subscriptions,1} => {any,[{c,atom,any,unknown}]},{emqx_mgmt_trace_proto_v1,read_trace_file,4} => {any,[{c,atom,any,unknown},{c,binary,{8,0},unknown},{c,number,{int_rng,0,pos_inf},integer},{c,number,{int_rng,0,pos_inf},integer}]},{emqx_bridge_proto_v5,start_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_proto_v1,clean_authz_cache,1} => {any,[{c,atom,any,unknown}]},{emqx_cm_proto_v1,get_chann_conn_mod,2} => {any,[{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_connector_proto_v1,start_connectors_to_all_nodes,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx,get_config,1} => {any,[{c,list,{any,{c,nil,[],unknown}},unknown}]},{emqx_node_rebalance_proto_v3,enable_rebalance_agent,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,identifier,[pid],unknown},any]},{emqx_proto_v2,clean_authz_cache,2} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}]},{emqx,reset_config,2} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,map,{[{{c,atom,[config],unknown},optional,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,{any,{c,nil,[],unknown}},unknown},none,none,none,{c,map,{[],{c,atom,any,unknown},any},unknown}],unknown}},{{c,atom,[post_config_update],unknown},optional,{c,map,{[],{c,atom,any,unknown},any},unknown}},{{c,atom,[raw_config],unknown},optional,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,{any,{c,nil,[],unknown}},unknown},none,none,none,{c,map,{[],{c,binary,{8,0},unknown},any},unknown}],unknown}}],none,none},unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,list,{{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,nil,[],unknown}},nonempty},any]},{emqx_conf_proto_v2,remove_config,3} => {any,[{c,atom,any,unknown},{c,list,{{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,nil,[],unknown}},nonempty},{c,map,{[{{c,atom,[lazy_evaluator],unknown},optional,{c,function,{{c,product,[{c,function,{any,any},unknown}],unknown},any},unknown}},{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_node_rebalance_proto_v1,evict_sessions,4} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,number,{int_rng,0,pos_inf},integer},{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,atom,[connected,connecting,disconnected,idle,reauthenticating],unknown}]},{emqx_alarm,delete_all_deactivated_alarms,0} => {any,[]},{emqx_delayed,delete_delayed_message,1} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},{c,atom,[not_found],unknown}],{2,{c,atom,[error],unknown}}},none,none],unknown},[any]},{emqx_bridge_proto_v2,start_bridges_to_all_nodes,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_conf_proto_v1,reset,3} => {any,[{c,atom,any,unknown},{c,list,{{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,nil,[],unknown}},nonempty},{c,map,{[{{c,atom,[lazy_evaluator],unknown},optional,{c,function,{{c,product,[{c,function,{any,any},unknown}],unknown},any},unknown}},{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_bridge_proto_v3,list_bridges,1} => {any,[{c,atom,any,unknown}]},{emqx_mgmt,do_list_subscriptions,0} => {none,[]},{emqx_mgmt_cluster_proto_v2,connected_replicants,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_rule_engine,reset_metrics_for_rule,1} => {{c,atom,[ok],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}]},{emqx_node_rebalance,session_count,0} => {{c,tuple,[{c,atom,[ok],unknown},any],{2,{c,atom,[ok],unknown}}},[]},{emqx_node_rebalance_proto_v3,connection_counts,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_authz_proto_v1,lookup_from_all_nodes,2} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,atom,any,unknown}]},{emqx_gateway_cm_proto_v1,call,4} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown},any]},{emqx_ds_replication_layer,do_store_batch_v1,4} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},none,none],unknown},[{c,atom,any,unknown},{c,binary,{8,0},unknown},{c,map,{[{{c,number,{int_set,[1]},integer},mandatory,{c,number,{int_set,[3]},integer}},{{c,number,{int_set,[2]},integer},mandatory,{c,list,{{c,tuple,[{c,atom,[message],unknown},{c,binary,{8,0},unknown},any,{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,map,{[],any,any},unknown},{c,map,{[],any,any},unknown},{c,binary,{8,0},unknown},{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{any,{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},none,none,none,none],unknown},{c,number,any,integer},any],{10,{c,atom,[message],unknown}}},{c,nil,[],unknown}},unknown}}],any,any},unknown},{c,map,{[],none,none},unknown}]},{emqx_management_proto_v2,unsubscribe,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,binary,{8,0},unknown}]},{emqx_management_proto_v3,unsubscribe,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,binary,{8,0},unknown}]},{emqx_proto_v1,get_metrics,1} => {any,[{c,atom,any,unknown}]},{emqx_slow_subs_api,get_history,0} => {{c,list,{{c,map,{[{{c,atom,[clientid],unknown},mandatory,{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}},{{c,atom,[last_update_time],unknown},mandatory,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[node],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[timespan],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[topic],unknown},mandatory,{c,binary,{8,0},unknown}}],none,none},unknown},{c,nil,[],unknown}},unknown},[]},{emqx_node_rebalance_proto_v1,available_nodes,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_proto_v1,get_alarms,2} => {any,[{c,atom,any,unknown},{c,atom,[activated,all,deactivated],unknown}]},{emqx_bridge_proto_v2,stop_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_persistent_session_ds_proto_v1,open_iterator,4} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,list,{{c,union,[{c,atom,['','#','+'],unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,nil,[],unknown}},unknown},{c,number,{int_rng,0,pos_inf},integer},any]},{emqx_connector_proto_v1,start_connector_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_cm,lookup_client,1} => {{c,list,{any,{c,nil,[],unknown}},unknown},[{c,tuple_set,[{2,[{c,tuple,[{c,atom,[clientid],unknown},any],{2,{c,atom,[clientid],unknown}}},{c,tuple,[{c,atom,[username],unknown},any],{2,{c,atom,[username],unknown}}}]}],unknown}]},{emqx_management_proto_v1,list_subscriptions,1} => {any,[{c,atom,any,unknown}]},{emqx_delayed_proto_v1,get_delayed_message,2} => {any,[{c,atom,any,unknown},{c,binary,{8,0},unknown}]},{emqx_bridge_proto_v3,lookup_from_all_nodes,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_exhook_mgr,server_hooks_metrics,1} => {any,[any]},{emqx_conf_proto_v1,update,3} => {any,[{c,list,{{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,nil,[],unknown}},nonempty},any,{c,map,{[{{c,atom,[lazy_evaluator],unknown},optional,{c,function,{{c,product,[{c,function,{any,any},unknown}],unknown},any},unknown}},{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_metrics_worker,get_metrics,2} => {{c,map,{[{{c,atom,[counters],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[gauges],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[rate],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[slides],unknown},mandatory,{c,map,{[],any,any},unknown}}],none,none},unknown},[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}]},{emqx_management_proto_v3,unsubscribe_batch,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,list,{{c,binary,{8,0},unknown},{c,nil,[],unknown}},unknown}]},{emqx_telemetry_proto_v1,get_cluster_uuid,1} => {any,[{c,atom,any,unknown}]},{emqx_mgmt_api_plugins_proto_v2,get_plugins,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_cm_proto_v2,kickout_client,2} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}]},{emqx_cm_proto_v1,kickout_client,2} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}]},{emqx_ds_proto_v1,store_batch,5} => {any,[{c,atom,any,unknown},{c,atom,any,unknown},{c,binary,{8,0},unknown},{c,map,{[{{c,number,{int_set,[1]},integer},mandatory,{c,number,{int_set,[3]},integer}},{{c,number,{int_set,[2]},integer},mandatory,{c,list,{{c,tuple,[{c,atom,[message],unknown},{c,binary,{8,0},unknown},any,{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,map,{[],{c,atom,any,unknown},{c,atom,[false,true],unknown}},unknown},{c,map,{[{{c,atom,[allow_publish],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[peerhost],unknown},optional,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown}},{{c,atom,[properties],unknown},optional,{c,map,{[],{c,atom,any,unknown},any},unknown}},{{c,atom,[proto_ver],unknown},optional,{c,union,[none,{c,binary,{8,0},unknown},none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none],unknown}},{{c,atom,[protocol],unknown},optional,{c,atom,any,unknown}},{{c,atom,[username],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}}],{c,atom,any,unknown},any},unknown},{c,binary,{8,0},unknown},{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{any,{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},{c,number,{int_rng,0,255},integer},none,none,none],unknown},{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},none,none,none,none],unknown},{c,number,any,integer},any],{10,{c,atom,[message],unknown}}},{c,nil,[],unknown}},unknown}}],none,none},unknown},{c,map,{[],none,none},unknown}]},{emqx_bridge_proto_v5,v2_get_metrics_from_all_nodes,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_ft_storage_exporter_fs_proxy,list_exports_local,1} => {any,[any]},{emqx_bridge_proto_v5,v2_start_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_persistent_session_ds,do_open_iterator,3} => {{c,tuple,[{c,atom,[error],unknown},{c,atom,[not_implemented],unknown}],{2,{c,atom,[error],unknown}}},[any,any,any]},{emqx_management_proto_v3,get_full_config,1} => {any,[{c,atom,any,unknown}]},{emqx_management_proto_v1,list_listeners,1} => {any,[{c,atom,any,unknown}]},{emqx_conf_proto_v1,reset,2} => {any,[{c,list,{{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,nil,[],unknown}},nonempty},{c,map,{[{{c,atom,[lazy_evaluator],unknown},optional,{c,function,{{c,product,[{c,function,{any,any},unknown}],unknown},any},unknown}},{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_cm_proto_v2,get_chann_conn_mod,2} => {any,[{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_conf_cli,get_config,1} => {{c,union,[none,none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},{c,list,{{c,number,{int_set,"_defknotuy"},integer},{c,nil,[],unknown}},nonempty}],{2,{c,atom,[error],unknown}}},none,{c,map,{[],any,any},unknown}],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_bridge_proto_v1,list_bridges,1} => {any,[{c,atom,any,unknown}]},{emqx_connector_api,lookup_from_local_node,2} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,atom,[not_found],unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},any],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_license_proto_v1,remote_connection_counts,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_bridge_proto_v5,v2_start_bridge_to_all_nodes,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_node_rebalance_proto_v1,evict_connections,2} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,number,{int_rng,0,pos_inf},integer}]},{emqx_gateway_cm_proto_v1,cast,4} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown},any]},{emqx_ds_replication_layer,do_make_iterator_v1,5} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,opaque,[{opaque,emqx_ds_storage_layer,iterator,0,{c,map,{[{{c,number,{int_set,[1]},integer},mandatory,{c,number,{int_set,[2]},integer}},{{c,number,{int_set,[2]},integer},mandatory,{c,number,{int_rng,0,1114111},integer}},{{c,number,{int_set,[3]},integer},mandatory,any}],none,none},unknown}}],unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,atom,any,unknown},{c,binary,{8,0},unknown},{c,opaque,[{opaque,emqx_ds_storage_layer,stream,0,{c,map,{[{{c,number,{int_set,[1]},integer},mandatory,{c,number,{int_set,[1]},integer}},{{c,number,{int_set,[2]},integer},mandatory,{c,number,{int_rng,0,1114111},integer}},{{c,number,{int_set,[3]},integer},mandatory,any}],none,none},unknown}}],unknown},{c,list,{{c,union,[{c,atom,['','#','+'],unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,nil,[],unknown}},unknown},{c,number,{int_rng,0,pos_inf},integer}]},{emqx_node_rebalance_purge,stop,0} => {any,[]},{emqx_conf_proto_v2,update,4} => {any,[{c,atom,any,unknown},{c,list,{{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,nil,[],unknown}},nonempty},any,{c,map,{[{{c,atom,[lazy_evaluator],unknown},optional,{c,function,{{c,product,[{c,function,{any,any},unknown}],unknown},any},unknown}},{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_ft_storage_fs_proxy,list_local,2} => {any,[any,any]},{emqx,remove_config,2} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,map,{[{{c,atom,[config],unknown},optional,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,{any,{c,nil,[],unknown}},unknown},none,none,none,{c,map,{[],{c,atom,any,unknown},any},unknown}],unknown}},{{c,atom,[post_config_update],unknown},optional,{c,map,{[],{c,atom,any,unknown},any},unknown}},{{c,atom,[raw_config],unknown},optional,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,{any,{c,nil,[],unknown}},unknown},none,none,none,{c,map,{[],{c,binary,{8,0},unknown},any},unknown}],unknown}}],none,none},unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,list,{{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,nil,[],unknown}},nonempty},{c,map,{[{{c,atom,[lazy_evaluator],unknown},optional,{c,function,{{c,product,[{c,function,{any,any},unknown}],unknown},any},unknown}},{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_license_resources,local_connection_count,0} => {any,[]},{emqx_mgmt_trace_proto_v2,get_trace_size,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_trace,trace_file_detail,1} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,map,{[{{c,atom,[file],unknown},mandatory,{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,union,[{c,atom,any,unknown},none,none,none,{c,list,{any,{c,nil,[],unknown}},unknown},{c,number,{int_rng,0,1114111},integer},none,none,none],unknown},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}},{{c,atom,[node],unknown},mandatory,{c,binary,{8,0},unknown}},{{c,atom,[reason],unknown},mandatory,{c,atom,any,unknown}}],none,none},unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,map,{[{{c,atom,[mtime],unknown},mandatory,{c,union,[{c,atom,[undefined],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},{c,tuple,[{c,tuple,[any,any,any],{3,any}},{c,tuple,[any,any,any],{3,any}}],{2,any}},none,none],unknown}},{{c,atom,[node],unknown},mandatory,{c,binary,{8,0},unknown}},{{c,atom,[size],unknown},mandatory,{c,union,[{c,atom,[undefined],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none],unknown}}],none,none},unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,union,[{c,atom,any,unknown},none,none,none,{c,list,{any,{c,nil,[],unknown}},unknown},{c,number,{int_rng,0,1114111},integer},none,none,none],unknown},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_bridge_proto_v3,start_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_gateway_cm_proto_v1,get_chan_info,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_mgmt_api_cluster,join,1} => {{c,union,[{c,atom,[ignore,ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},none,none],unknown},[{c,atom,any,unknown}]},{emqx_ds_replication_layer,do_get_streams_v1,4} => {{c,list,{{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,opaque,[{opaque,emqx_ds_storage_layer,stream,0,{c,map,{[{{c,number,{int_set,[1]},integer},mandatory,{c,number,{int_set,[1]},integer}},{{c,number,{int_set,[2]},integer},mandatory,{c,number,{int_rng,0,1114111},integer}},{{c,number,{int_set,[3]},integer},mandatory,any}],none,none},unknown}}],unknown}],{2,any}},{c,nil,[],unknown}},unknown},[{c,atom,any,unknown},{c,binary,{8,0},unknown},{c,list,{{c,union,[{c,atom,['','#','+'],unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,nil,[],unknown}},unknown},{c,number,{int_rng,0,pos_inf},integer}]},{emqx_mgmt_api_trace,get_trace_size,0} => {{c,map,{[],any,any},unknown},[]},{emqx_ft_storage_fs_proto_v1,multilist,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,tuple,[{c,binary,{8,0},unknown},{c,binary,{8,0},unknown}],{2,any}},{c,atom,[fragment,result],unknown}]},{emqx_broker,subscriptions,1} => {{c,list,{{c,tuple,[any,any],{2,any}},{c,nil,[],unknown}},unknown},[{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,{c,identifier,[pid],unknown},none,none,none,none,none],unknown}]},{emqx_cm_proto_v1,get_chan_info,2} => {any,[{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_proto_v2,is_running,1} => {any,[{c,atom,any,unknown}]},{emqx_ft_storage_fs_reader,read,2} => {any,[{c,identifier,[pid],unknown},{c,number,{int_rng,1,pos_inf},integer}]},{emqx_management_proto_v3,call_client,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},any]},{emqx_node_rebalance_proto_v2,enable_rebalance_agent,2} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,identifier,[pid],unknown}]},{emqx_bridge_proto_v2,start_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_cm,takeover_finish,2} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,atom,[noproc,timeout,unexpected_exception],unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},any],{2,{c,atom,[ok],unknown}}}]}],unknown},none,none],unknown},[{c,atom,any,unknown},{c,identifier,[pid],unknown}]},{emqx_conf_app,get_override_config_file,0} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,map,{[{{c,atom,[msg],unknown},mandatory,any},{{c,atom,[node],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[release],unknown},mandatory,{c,list,{any,{c,nil,[],unknown}},nonempty}},{{c,atom,[wall_clock],unknown},mandatory,{c,tuple,[any,any],{2,any}}}],none,none},unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},any],{2,{c,atom,[ok],unknown}}}]}],unknown},[]},{emqx_management_proto_v1,broker_info,1} => {any,[{c,atom,any,unknown}]},{emqx_ds_proto_v1,get_streams,5} => {any,[{c,atom,any,unknown},{c,atom,any,unknown},{c,binary,{8,0},unknown},{c,list,{{c,union,[{c,atom,['','#','+'],unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,nil,[],unknown}},unknown},{c,number,{int_rng,0,pos_inf},integer}]},{emqx_mgmt,node_info,0} => {{c,map,{[{{c,atom,[connections],unknown},mandatory,any},{{c,atom,[edition],unknown},mandatory,{c,binary,{0,80},unknown}},{{c,atom,[live_connections],unknown},mandatory,any},{{c,atom,[load1],unknown},optional,{c,number,any,float}},{{c,atom,[load15],unknown},optional,{c,number,any,float}},{{c,atom,[load5],unknown},optional,{c,number,any,float}},{{c,atom,[log_path],unknown},mandatory,{c,binary,{8,0},unknown}},{{c,atom,[max_fds],unknown},mandatory,any},{{c,atom,[memory_total],unknown},mandatory,{c,number,any,unknown}},{{c,atom,[memory_used],unknown},mandatory,{c,number,any,integer}},{{c,atom,[node],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[node_status],unknown},mandatory,{c,atom,[running],unknown}},{{c,atom,[otp_release],unknown},mandatory,{c,binary,{8,0},unknown}},{{c,atom,[process_available],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[process_used],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[role],unknown},mandatory,{c,atom,[core,replicant],unknown}},{{c,atom,[sys_path],unknown},mandatory,{c,binary,{8,0},unknown}},{{c,atom,[uptime],unknown},mandatory,any},{{c,atom,[version],unknown},mandatory,{c,binary,{8,0},unknown}}],none,none},unknown},[]},{emqx_node_rebalance_api_proto_v2,node_rebalance_start,2} => {any,[{c,atom,any,unknown},{c,map,{[{{c,atom,[abs_conn_threshold],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[abs_sess_threshold],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[conn_evict_rate],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[nodes],unknown},optional,{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}},{{c,atom,[rel_conn_threshold],unknown},optional,{c,number,any,unknown}},{{c,atom,[rel_sess_threshold],unknown},optional,{c,number,any,unknown}},{{c,atom,[sess_evict_rate],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[wait_health_check],unknown},optional,{c,number,any,unknown}},{{c,atom,[wait_takeover],unknown},optional,{c,number,any,unknown}}],none,none},unknown}]},{emqx_mgmt_data_backup_proto_v1,delete_file,3} => {any,[{c,atom,any,unknown},{c,binary,{8,0},unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none],unknown}]},{emqx_broker,subscriptions_via_topic,1} => {{c,list,{any,{c,nil,[],unknown}},unknown},[any]},{emqx_authz_cache,drain_cache,0} => {{c,atom,[ok],unknown},[]},{emqx_bridge_proto_v5,v2_lookup_from_all_nodes,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_broker_proto_v1,list_subscriptions_via_topic,2} => {any,[{c,atom,any,unknown},{c,binary,{8,0},unknown}]},{emqx_resource,recreate_local,4} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,atom,[not_found,updating_to_incorrect_resource_type],unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,map,{[{{c,atom,[added_channels],unknown},mandatory,any},{{c,atom,[callback_mode],unknown},mandatory,{c,atom,[always_sync,async_if_possible],unknown}},{{c,atom,[config],unknown},mandatory,any},{{c,atom,[error],unknown},mandatory,any},{{c,atom,[id],unknown},mandatory,{c,binary,{8,0},unknown}},{{c,atom,[mod],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[query_mode],unknown},mandatory,{c,atom,[async,no_queries,simple_async,simple_async_internal_buffer,simple_sync,simple_sync_internal_buffer,sync],unknown}},{{c,atom,[state],unknown},mandatory,any},{{c,atom,[status],unknown},mandatory,{c,atom,[connected,connecting,disconnected,stopped],unknown}}],none,none},unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,binary,{8,0},unknown},{c,atom,any,unknown},any,{c,map,{[{{c,atom,[auto_restart_interval],unknown},optional,{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,1,pos_inf},integer},none,none,none],unknown}},{{c,atom,[auto_retry_interval],unknown},optional,{c,number,any,integer}},{{c,atom,[batch_size],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[batch_time],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[health_check_interval],unknown},optional,{c,number,any,integer}},{{c,atom,[health_check_timeout],unknown},optional,{c,number,any,integer}},{{c,atom,[inflight_window],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[max_buffer_bytes],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[query_mode],unknown},optional,{c,atom,[async,no_queries,simple_async,simple_async_internal_buffer,simple_sync,simple_sync_internal_buffer,sync],unknown}},{{c,atom,[resume_interval],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[spawn_buffer_workers],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[start_after_created],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[start_timeout],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[wait_for_resource_ready],unknown},optional,{c,number,any,integer}},{{c,atom,[worker_pool_size],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}}],none,none},unknown}]},{emqx_shared_sub_proto_v1,send,4} => {any,[{c,atom,any,unknown},{c,identifier,[pid],unknown},{c,binary,{8,0},unknown},any]},{emqx_conf_app,sync_data_from_node,0} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,binary,{8,0},unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},[]},{emqx_conf_proto_v2,remove_config,2} => {any,[{c,list,{{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,nil,[],unknown}},nonempty},{c,map,{[{{c,atom,[lazy_evaluator],unknown},optional,{c,function,{{c,product,[{c,function,{any,any},unknown}],unknown},any},unknown}},{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_conf_proto_v3,reset,2} => {any,[{c,list,{{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,nil,[],unknown}},nonempty},{c,map,{[{{c,atom,[lazy_evaluator],unknown},optional,{c,function,{{c,product,[{c,function,{any,any},unknown}],unknown},any},unknown}},{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_node_rebalance_proto_v3,disconnected_session_counts,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_management_proto_v2,unsubscribe_batch,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,list,{{c,binary,{8,0},unknown},{c,nil,[],unknown}},unknown}]},{emqx_topic_metrics_proto_v1,reset,2} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,binary,{8,0},unknown}]},{emqx_management_proto_v4,list_subscriptions,1} => {any,[{c,atom,any,unknown}]},{emqx_connector,list,0} => {any,[]},{emqx_management_proto_v3,list_listeners,1} => {any,[{c,atom,any,unknown}]},{emqx_broker,dispatch,2} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,atom,[no_subscribers,not_running],unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,number,{int_rng,0,pos_inf},integer}],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,binary,{8,0},unknown},{c,tuple,[{c,atom,[delivery],unknown},{c,identifier,[pid],unknown},{c,tuple,[{c,atom,[message],unknown},{c,binary,{8,0},unknown},any,{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,map,{[],{c,atom,any,unknown},{c,atom,[false,true],unknown}},unknown},{c,map,{[{{c,atom,[allow_publish],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[peerhost],unknown},optional,{c,tuple_set,[{4,[{c,tuple,[any,any,any,any],{4,any}}]},{8,[{c,tuple,[any,any,any,any,any,any,any,any],{8,any}}]}],unknown}},{{c,atom,[properties],unknown},optional,{c,map,{[],any,any},unknown}},{{c,atom,[proto_ver],unknown},optional,{c,union,[none,{c,binary,{8,0},unknown},none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none],unknown}},{{c,atom,[protocol],unknown},optional,{c,atom,any,unknown}},{{c,atom,[username],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}}],{c,atom,any,unknown},any},unknown},{c,binary,{8,0},unknown},{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{any,{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},{c,number,{int_rng,0,255},integer},none,none,none],unknown},{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},none,none,none,none],unknown},{c,number,any,integer},any],{10,{c,atom,[message],unknown}}}],{3,{c,atom,[delivery],unknown}}}]},{emqx,update_config,3} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,map,{[{{c,atom,[config],unknown},optional,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,{any,{c,nil,[],unknown}},unknown},none,none,none,{c,map,{[],{c,atom,any,unknown},any},unknown}],unknown}},{{c,atom,[post_config_update],unknown},optional,{c,map,{[],{c,atom,any,unknown},any},unknown}},{{c,atom,[raw_config],unknown},optional,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,{any,{c,nil,[],unknown}},unknown},none,none,none,{c,map,{[],{c,binary,{8,0},unknown},any},unknown}],unknown}}],none,none},unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,list,{{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,nil,[],unknown}},nonempty},any,{c,map,{[{{c,atom,[lazy_evaluator],unknown},optional,{c,function,{{c,product,[{c,function,{any,any},unknown}],unknown},any},unknown}},{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_mgmt_api_plugins,ensure_action,2} => {{c,atom,[ok],unknown},[{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,atom,[restart,start,stop],unknown}]},{emqx_management_proto_v2,call_client,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},any]},{emqx_plugins,get_tar,1} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,binary,{8,0},unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{any,{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},{c,number,{int_rng,0,1114111},integer},none,none,none],unknown}]},{emqx_bridge_proto_v1,restart_bridges_to_all_nodes,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_bridge_proto_v2,restart_bridges_to_all_nodes,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_management_proto_v1,subscribe,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,list,{{c,tuple,[{c,binary,{8,0},unknown},{c,map,{[{{c,atom,[nl],unknown},mandatory,{c,number,{int_set,[0,1]},integer}},{{c,atom,[qos],unknown},mandatory,{c,number,{int_set,[0,1,2]},integer}},{{c,atom,[rap],unknown},mandatory,{c,number,{int_set,[0,1]},integer}},{{c,atom,[rh],unknown},mandatory,{c,number,{int_set,[0,1,2]},integer}}],{c,atom,any,unknown},any},unknown}],{2,any}},{c,nil,[],unknown}},unknown}]},{emqx_mgmt_api_plugins_proto_v2,install_package,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,binary,{8,0},unknown}]},{emqx_bridge_proto_v2,stop_bridges_to_all_nodes,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_bridge_proto_v4,restart_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_bridge_proto_v3,restart_bridges_to_all_nodes,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_conf_proto_v3,remove_config,3} => {any,[{c,atom,any,unknown},{c,list,{{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,nil,[],unknown}},nonempty},{c,map,{[{{c,atom,[lazy_evaluator],unknown},optional,{c,function,{{c,product,[{c,function,{any,any},unknown}],unknown},any},unknown}},{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_bridge_proto_v5,restart_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_proto_v1,get_stats,1} => {any,[{c,atom,any,unknown}]},{emqx_conf_proto_v1,remove_config,3} => {any,[{c,atom,any,unknown},{c,list,{{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,nil,[],unknown}},nonempty},{c,map,{[{{c,atom,[lazy_evaluator],unknown},optional,{c,function,{{c,product,[{c,function,{any,any},unknown}],unknown},any},unknown}},{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_delayed,clear_all_local,0} => {{c,atom,[ok],unknown},[]},{emqx_node_rebalance_api_proto_v1,node_rebalance_evacuation_stop,1} => {any,[{c,atom,any,unknown}]},{emqx_mgmt_api_plugins_proto_v1,describe_package,1} => {any,[{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_node_rebalance_proto_v3,available_nodes,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_bridge_resource,start,2} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},none,none],unknown},[any,{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{any,{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},{c,number,{int_rng,0,255},integer},none,none,none],unknown},{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},none,none,none,none],unknown}]},{emqx_management_proto_v4,node_info,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_bridge_proto_v1,stop_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_mgmt,do_call_client,2} => {any,[{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},any]},{emqx_conf_proto_v1,get_config,2} => {any,[{c,atom,any,unknown},{c,list,{{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,nil,[],unknown}},unknown}]},{emqx_conf_proto_v1,update,4} => {any,[{c,atom,any,unknown},{c,list,{{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,nil,[],unknown}},nonempty},any,{c,map,{[{{c,atom,[lazy_evaluator],unknown},optional,{c,function,{{c,product,[{c,function,{any,any},unknown}],unknown},any},unknown}},{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_persistent_session_ds,do_ensure_all_iterators_closed,1} => {{c,atom,[ok],unknown},[any]},{emqx_bridge_resource,restart,2} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},none,none],unknown},[any,{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{any,{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},{c,number,{int_rng,0,255},integer},none,none,none],unknown},{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},none,none,none,none],unknown}]},{emqx_node_rebalance_status_proto_v2,purge_status,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_bridge_proto_v4,stop_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_dashboard_proto_v1,current_rate,1} => {any,[{c,atom,any,unknown}]},{emqx_node_rebalance_api_proto_v2,node_rebalance_purge_stop,1} => {any,[{c,atom,any,unknown}]},{emqx_bridge_api,get_metrics_from_local_node,2} => {{c,map,{[{{c,atom,[dropped],unknown},mandatory,{c,number,any,integer}},{{c,atom,['dropped.expired'],unknown},mandatory,{c,number,any,integer}},{{c,atom,['dropped.other'],unknown},mandatory,{c,number,any,integer}},{{c,atom,['dropped.queue_full'],unknown},mandatory,{c,number,any,integer}},{{c,atom,['dropped.resource_not_found'],unknown},mandatory,{c,number,any,integer}},{{c,atom,['dropped.resource_stopped'],unknown},mandatory,{c,number,any,integer}},{{c,atom,[failed],unknown},mandatory,{c,number,any,integer}},{{c,atom,[inflight],unknown},mandatory,any},{{c,atom,[late_reply],unknown},mandatory,{c,number,any,integer}},{{c,atom,[matched],unknown},mandatory,{c,number,any,integer}},{{c,atom,[queuing],unknown},mandatory,any},{{c,atom,[rate],unknown},mandatory,any},{{c,atom,[rate_last5m],unknown},mandatory,any},{{c,atom,[rate_max],unknown},mandatory,any},{{c,atom,[received],unknown},mandatory,{c,number,any,integer}},{{c,atom,[retried],unknown},mandatory,{c,number,any,integer}},{{c,atom,[success],unknown},mandatory,{c,number,any,integer}}],none,none},unknown},[{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{any,{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},{c,number,{int_rng,0,255},integer},none,none,none],unknown},{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{any,{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},{c,number,{int_rng,0,255},integer},none,none,none],unknown},{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},none,none,none,none],unknown}]},{emqx_trace,trace_file,1} => {{c,tuple_set,[{3,[{c,tuple,[{c,atom,[error],unknown},{c,list,{{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}},unknown},{c,atom,any,unknown}],{3,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,list,{{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}},unknown},{c,binary,{8,0},unknown}],{3,{c,atom,[ok],unknown}}}]}],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,union,[{c,atom,any,unknown},none,none,none,{c,list,{any,{c,nil,[],unknown}},unknown},{c,number,{int_rng,0,1114111},integer},none,none,none],unknown},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_cm_proto_v1,kick_session,3} => {any,[{c,atom,[discard,kick],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_bridge_proto_v4,get_metrics_from_all_nodes,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_bridge_proto_v3,stop_bridges_to_all_nodes,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_exhook_proto_v1,all_servers_info,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_mgmt_api_configs,get_full_config,0} => {{c,map,{[],any,any},unknown},[]},{emqx_mgmt_api_plugins,delete_package,1} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},none,none],unknown},[{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_mgmt_data_backup,read_file,1} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,atom,any,unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,binary,{8,0},unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},none,none],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{any,{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},{c,number,{int_rng,0,1114111},integer},none,none,none],unknown},{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},none,none,none,none],unknown}]},{emqx_topic_metrics_proto_v1,reset,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_conf_proto_v2,reset,3} => {any,[{c,atom,any,unknown},{c,list,{{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,nil,[],unknown}},nonempty},{c,map,{[{{c,atom,[lazy_evaluator],unknown},optional,{c,function,{{c,product,[{c,function,{any,any},unknown}],unknown},any},unknown}},{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_node_rebalance_agent,disable,1} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},{c,atom,[already_disabled,invalid_coordinator],unknown}],{2,{c,atom,[error],unknown}}},none,none],unknown},[{c,identifier,[pid],unknown}]},{emqx_bridge_v2_api,lookup_from_local_node,2} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,atom,[not_found],unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},any],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_management_proto_v2,subscribe,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,list,{{c,tuple,[{c,binary,{8,0},unknown},{c,map,{[{{c,atom,[nl],unknown},mandatory,{c,number,{int_set,[0,1]},integer}},{{c,atom,[qos],unknown},mandatory,{c,number,{int_set,[0,1,2]},integer}},{{c,atom,[rap],unknown},mandatory,{c,number,{int_set,[0,1]},integer}},{{c,atom,[rh],unknown},mandatory,{c,number,{int_set,[0,1,2]},integer}}],{c,atom,any,unknown},any},unknown}],{2,any}},{c,nil,[],unknown}},unknown}]},{emqx_node_rebalance_proto_v1,session_counts,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_eviction_agent_proto_v1,evict_session_channel,4} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,map,{[{{c,atom,[clean_start],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[clientid],unknown},optional,{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}},{{c,atom,[conn_mod],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[conn_props],unknown},optional,{c,map,{[],{c,atom,any,unknown},any},unknown}},{{c,atom,[connected],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[connected_at],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[disconnected_at],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[expiry_interval],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[keepalive],unknown},optional,{c,number,{int_rng,0,1114111},integer}},{{c,atom,[peercert],unknown},optional,{c,union,[{c,atom,[nossl,undefined],unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,union,[{c,atom,any,unknown},none,none,none,none,none,{c,tuple,any,{any,any}},none,none],unknown},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}},{{c,atom,[peername],unknown},mandatory,{c,tuple,[{c,union,[{c,atom,[local,undefined,unspec],unknown},none,none,none,none,none,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown},none,none],unknown},any],{2,any}}},{{c,atom,[proto_name],unknown},optional,{c,binary,{8,0},unknown}},{{c,atom,[proto_ver],unknown},optional,{c,union,[none,{c,binary,{8,0},unknown},none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none],unknown}},{{c,atom,[receive_maximum],unknown},optional,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[sockname],unknown},mandatory,{c,tuple,[{c,union,[{c,atom,[local,undefined,unspec],unknown},none,none,none,none,none,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown},none,none],unknown},any],{2,any}}},{{c,atom,[socktype],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[username],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}}],{c,atom,any,unknown},any},unknown},{c,map,{[{{c,atom,[anonymous],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[auth_result],unknown},optional,{c,atom,[bad_authentication_method,bad_clientid_or_password,bad_username_or_password,banned,client_identifier_not_valid,not_authorized,server_busy,server_unavailable,success],unknown}},{{c,atom,[clientid],unknown},mandatory,{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}},{{c,atom,[cn],unknown},optional,{c,binary,{8,0},unknown}},{{c,atom,[dn],unknown},optional,{c,binary,{8,0},unknown}},{{c,atom,[is_bridge],unknown},mandatory,{c,atom,[false,true],unknown}},{{c,atom,[is_superuser],unknown},mandatory,{c,atom,[false,true],unknown}},{{c,atom,[mountpoint],unknown},mandatory,{c,union,[{c,atom,[undefined],unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}},{{c,atom,[password],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}},{{c,atom,[peerhost],unknown},mandatory,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown}},{{c,atom,[protocol],unknown},mandatory,{c,atom,any,unknown}},{{c,atom,[sockport],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[username],unknown},mandatory,{c,union,[{c,atom,[undefined],unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}},{{c,atom,[ws_cookie],unknown},optional,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,{any,{c,nil,[],unknown}},unknown},none,none,none,none],unknown}},{{c,atom,[zone],unknown},mandatory,{c,atom,any,unknown}}],{c,atom,any,unknown},any},unknown}]},{emqx_eviction_agent,evict_connections,1} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},{c,atom,[disabled],unknown}],{2,{c,atom,[error],unknown}}},none,none],unknown},[any]},{emqx_conf_proto_v1,get_config,3} => {any,[{c,atom,any,unknown},{c,list,{{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,nil,[],unknown}},unknown},any]},{emqx_node_rebalance_proto_v2,enable_rebalance_agent,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,identifier,[pid],unknown},any]},{emqx_ft_storage_exporter_fs_proto_v1,read_export_file,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},none,none,none,{c,list,{{c,union,[{c,atom,any,unknown},none,none,none,{c,list,{any,{c,nil,[],unknown}},unknown},{c,number,{int_rng,0,1114111},integer},none,none,none],unknown},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_prometheus_proto_v1,start,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_cm_proto_v1,lookup_client,2} => {any,[{c,atom,any,unknown},{c,tuple_set,[{2,[{c,tuple,[{c,atom,[clientid],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}],{2,{c,atom,[clientid],unknown}}},{c,tuple,[{c,atom,[username],unknown},{c,union,[{c,atom,[undefined],unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}],{2,{c,atom,[username],unknown}}}]}],unknown}]},{emqx_mgmt_data_backup_proto_v1,read_file,3} => {any,[{c,atom,any,unknown},{c,binary,{8,0},unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none],unknown}]},{emqx_authn_api,lookup_from_local_node,2} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,tuple,[{c,atom,any,unknown},{c,union,[{c,atom,[not_found_resource],unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}],{2,any}}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,tuple,[{c,atom,any,unknown},{c,atom,[connected,connecting,disconnected,stopped],unknown},{c,map,{[{{c,atom,[counters],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[gauges],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[rate],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[slides],unknown},mandatory,{c,map,{[],any,any},unknown}}],none,none},unknown},{c,map,{[{{c,atom,[counters],unknown},optional,{c,map,{[],any,any},unknown}},{{c,atom,[gauges],unknown},optional,{c,map,{[],any,any},unknown}},{{c,atom,[rate],unknown},optional,{c,map,{[],any,any},unknown}},{{c,atom,[slides],unknown},optional,{c,map,{[],any,any},unknown}}],none,none},unknown}],{4,any}}],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,atom,any,unknown},{c,binary,{8,0},unknown}]},{emqx_gateway_cm_proto_v1,call,5} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown},any,{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none],unknown}]},{emqx_cm_proto_v2,lookup_client,2} => {any,[{c,atom,any,unknown},{c,tuple_set,[{2,[{c,tuple,[{c,atom,[clientid],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}],{2,{c,atom,[clientid],unknown}}},{c,tuple,[{c,atom,[username],unknown},{c,union,[{c,atom,[undefined],unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}],{2,{c,atom,[username],unknown}}}]}],unknown}]},{emqx_persistent_session_ds_proto_v1,close_iterator,2} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},any]},{emqx_conf_proto_v2,sync_data_from_node,1} => {any,[{c,atom,any,unknown}]},{emqx_bridge_proto_v1,restart_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_management_proto_v4,subscribe,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,list,{{c,tuple,[{c,binary,{8,0},unknown},{c,map,{[{{c,atom,[nl],unknown},mandatory,{c,number,{int_set,[0,1]},integer}},{{c,atom,[qos],unknown},mandatory,{c,number,{int_set,[0,1,2]},integer}},{{c,atom,[rap],unknown},mandatory,{c,number,{int_set,[0,1]},integer}},{{c,atom,[rh],unknown},mandatory,{c,number,{int_set,[0,1,2]},integer}}],{c,atom,any,unknown},any},unknown}],{2,any}},{c,nil,[],unknown}},unknown}]},{emqx_bridge,list,0} => {{c,list,{any,{c,nil,[],unknown}},unknown},[]},{emqx_management_proto_v4,list_listeners,1} => {any,[{c,atom,any,unknown}]},{emqx_node_rebalance_proto_v2,disconnected_session_counts,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_management_proto_v1,get_full_config,1} => {any,[{c,atom,any,unknown}]},{emqx_node_rebalance_agent,enable,3} => {any,[any,any,any]},{emqx_node_rebalance_status_proto_v2,evacuation_status,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_node_rebalance,disconnected_session_count,0} => {{c,tuple,[{c,atom,[ok],unknown},any],{2,{c,atom,[ok],unknown}}},[]},{emqx_broker_proto_v1,forward_async,3} => {any,[{c,atom,any,unknown},{c,binary,{8,0},unknown},{c,tuple,[{c,atom,[delivery],unknown},{c,identifier,[pid],unknown},{c,tuple,[{c,atom,[message],unknown},{c,binary,{8,0},unknown},any,{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,map,{[],{c,atom,any,unknown},{c,atom,[false,true],unknown}},unknown},{c,map,{[{{c,atom,[allow_publish],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[peerhost],unknown},optional,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown}},{{c,atom,[properties],unknown},optional,{c,map,{[],{c,atom,any,unknown},any},unknown}},{{c,atom,[proto_ver],unknown},optional,{c,union,[none,{c,binary,{8,0},unknown},none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none],unknown}},{{c,atom,[protocol],unknown},optional,{c,atom,any,unknown}},{{c,atom,[username],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}}],{c,atom,any,unknown},any},unknown},{c,binary,{8,0},unknown},{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{any,{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},{c,number,{int_rng,0,255},integer},none,none,none],unknown},{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},none,none,none,none],unknown},{c,number,any,integer},any],{10,{c,atom,[message],unknown}}}],{3,{c,atom,[delivery],unknown}}}]},{emqx_topic_metrics,metrics,1} => {{c,union,[none,none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},{c,atom,[topic_not_found],unknown}],{2,{c,atom,[error],unknown}}},none,{c,map,{[{{c,atom,[create_time],unknown},mandatory,any},{{c,atom,[metrics],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[reset_time],unknown},optional,any},{{c,atom,[topic],unknown},mandatory,any}],none,none},unknown}],unknown},[any]},{emqx_resource,reset_metrics_local,1} => {{c,atom,[ok],unknown},[{c,binary,{8,0},unknown}]},{emqx_proto_v1,clean_authz_cache,2} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}]},{emqx_node_rebalance_proto_v3,enable_rebalance_agent,4} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,identifier,[pid],unknown},any,{c,map,{[{{c,atom,[allow_connections],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_slow_subs_proto_v1,clear_history,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_eviction_agent,all_local_channels_count,0} => {any,[]},{emqx_management_proto_v2,broker_info,1} => {any,[{c,atom,any,unknown}]},{emqx_topic_metrics,reset,1} => {any,[any]},{emqx_management_proto_v3,node_info,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_ds_proto_v1,drop_db,2} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,atom,any,unknown}]},{emqx_management_proto_v3,broker_info,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_bridge_proto_v4,lookup_from_all_nodes,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_node_rebalance_proto_v1,connection_counts,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_topic_metrics,reset,0} => {any,[]},{emqx_bridge_proto_v4,stop_bridges_to_all_nodes,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_bridge_proto_v2,restart_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_mgmt,do_kickout_clients,1} => {{c,atom,[ok],unknown},[{c,list,{any,{c,nil,[],unknown}},unknown}]},{emqx_conf_proto_v3,remove_config,2} => {any,[{c,list,{{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,nil,[],unknown}},nonempty},{c,map,{[{{c,atom,[lazy_evaluator],unknown},optional,{c,function,{{c,product,[{c,function,{any,any},unknown}],unknown},any},unknown}},{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_node_rebalance_proto_v3,disable_rebalance_agent,2} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,identifier,[pid],unknown}]},{emqx_ds_replication_layer,do_next_v1,4} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,atom,[end_of_stream],unknown}],{2,{c,atom,[ok],unknown}}}]},{3,[{c,tuple,[{c,atom,[ok],unknown},{c,opaque,[{opaque,emqx_ds_storage_layer,iterator,0,{c,map,{[{{c,number,{int_set,[1]},integer},mandatory,{c,number,{int_set,[2]},integer}},{{c,number,{int_set,[2]},integer},mandatory,{c,number,{int_rng,0,1114111},integer}},{{c,number,{int_set,[3]},integer},mandatory,any}],none,none},unknown}}],unknown},{c,list,{{c,tuple,[{c,atom,[message],unknown},{c,binary,{8,0},unknown},any,{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,map,{[],any,any},unknown},{c,map,{[],any,any},unknown},{c,binary,{8,0},unknown},{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{any,{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},none,none,none,none],unknown},{c,number,any,integer},any],{10,{c,atom,[message],unknown}}},{c,nil,[],unknown}},unknown}],{3,{c,atom,[ok],unknown}}}]}],unknown},[{c,atom,any,unknown},{c,binary,{8,0},unknown},{c,opaque,[{opaque,emqx_ds_storage_layer,iterator,0,{c,map,{[{{c,number,{int_set,[1]},integer},mandatory,{c,number,{int_set,[2]},integer}},{{c,number,{int_set,[2]},integer},mandatory,{c,number,{int_rng,0,1114111},integer}},{{c,number,{int_set,[3]},integer},mandatory,any}],none,none},unknown}}],unknown},{c,number,{int_rng,1,pos_inf},integer}]},{emqx_node_rebalance_purge_proto_v1,start,2} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,map,{[{{c,atom,[purge_rate],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}}],none,none},unknown}]},{emqx_cm,takeover_session,2} => {{c,union,[{c,atom,[none,ok,undefined],unknown},none,none,none,{c,list,{{c,tuple,[{c,atom,any,unknown},any],{2,any}},{c,nil,[],unknown}},unknown},none,{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[expired],unknown},{c,union,[none,none,none,none,none,none,{c,tuple,[{c,atom,[session],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},any,{c,atom,[false,true],unknown},{c,map,{[],any,any},unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none],unknown},{c,atom,[false,true],unknown},{c,opaque,[{opaque,emqx_inflight,inflight,0,{c,tuple,[any,any,any],{3,any}}}],unknown},{c,tuple,[any,any,any,any,any,any,any,any,any,any,any],{11,any}},{c,number,{int_rng,1,1114111},integer},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none],unknown},{c,map,{[],any,any},unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none],unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none],unknown},{c,number,{int_rng,1,pos_inf},integer}],{15,{c,atom,[session],unknown}}},none,{c,map,{[{{c,atom,[conninfo],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[created_at],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[id],unknown},mandatory,{c,binary,{8,0},unknown}},{{c,atom,[inflight],unknown},mandatory,{c,opaque,[{opaque,emqx_persistent_message_ds_replayer,inflight,0,{c,tuple,[any,any,any,any],{4,any}}}],unknown}},{{c,atom,[last_alive_at],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[props],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[receive_maximum],unknown},mandatory,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[subscriptions],unknown},mandatory,{c,opaque,[{opaque,emqx_topic_gbt,t,2,{c,opaque,[{opaque,gb_trees,tree,2,{c,tuple,[any,any],{2,any}}}],unknown}}],unknown}},{{c,atom,[timer_bump_last_alive_at],unknown},optional,{c,identifier,[reference],unknown}},{{c,atom,[timer_get_streams],unknown},optional,{c,identifier,[reference],unknown}},{{c,atom,[timer_pull],unknown},optional,{c,identifier,[reference],unknown}}],none,none},unknown}],unknown}],{2,{c,atom,[expired],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,union,[none,none,none,none,{c,list,{{c,tuple,[any,any,any],{3,any}},{c,nil,[],unknown}},unknown},none,none,none,{c,map,{[],any,any},unknown}],unknown}],{2,{c,atom,[ok],unknown}}},{c,tuple,[{c,atom,[persistent],unknown},{c,union,[none,none,none,none,none,none,{c,tuple,[{c,atom,[session],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},any,{c,atom,[false,true],unknown},{c,map,{[],any,any},unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none],unknown},{c,atom,[false,true],unknown},{c,opaque,[{opaque,emqx_inflight,inflight,0,{c,tuple,[any,any,any],{3,any}}}],unknown},{c,tuple,[any,any,any,any,any,any,any,any,any,any,any],{11,any}},{c,number,{int_rng,1,1114111},integer},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none],unknown},{c,map,{[],any,any},unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none],unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none],unknown},{c,number,{int_rng,1,pos_inf},integer}],{15,{c,atom,[session],unknown}}},none,{c,map,{[{{c,atom,[conninfo],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[created_at],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[id],unknown},mandatory,{c,binary,{8,0},unknown}},{{c,atom,[inflight],unknown},mandatory,{c,opaque,[{opaque,emqx_persistent_message_ds_replayer,inflight,0,{c,tuple,[any,any,any,any],{4,any}}}],unknown}},{{c,atom,[last_alive_at],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[props],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[receive_maximum],unknown},mandatory,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[subscriptions],unknown},mandatory,{c,opaque,[{opaque,emqx_topic_gbt,t,2,{c,opaque,[{opaque,gb_trees,tree,2,{c,tuple,[any,any],{2,any}}}],unknown}}],unknown}},{{c,atom,[timer_bump_last_alive_at],unknown},optional,{c,identifier,[reference],unknown}},{{c,atom,[timer_get_streams],unknown},optional,{c,identifier,[reference],unknown}},{{c,atom,[timer_pull],unknown},optional,{c,identifier,[reference],unknown}}],none,none},unknown}],unknown}],{2,{c,atom,[persistent],unknown}}}]},{4,[{c,tuple,[{c,atom,[living],unknown},{c,atom,any,unknown},{c,identifier,[pid],unknown},any],{4,{c,atom,[living],unknown}}}]}],unknown},none,{c,map,{[],{c,atom,any,unknown},any},unknown}],unknown},[any,any]},{emqx_conf_proto_v2,reset,2} => {any,[{c,list,{{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,nil,[],unknown}},nonempty},{c,map,{[{{c,atom,[lazy_evaluator],unknown},optional,{c,function,{{c,product,[{c,function,{any,any},unknown}],unknown},any},unknown}},{{c,atom,[override_to],unknown},optional,{c,atom,[cluster,local],unknown}},{{c,atom,[persistent],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[rawconf_with_defaults],unknown},optional,{c,atom,[false,true],unknown}}],none,none},unknown}]},{emqx_authz_api_sources,lookup_from_local_node,1} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,tuple,[{c,atom,any,unknown},{c,union,[{c,atom,[not_found_resource],unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}],{2,any}}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,tuple,[{c,atom,any,unknown},{c,atom,[connected,connecting,disconnected,stopped],unknown},{c,map,{[{{c,atom,[counters],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[gauges],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[rate],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[slides],unknown},mandatory,{c,map,{[],any,any},unknown}}],none,none},unknown},{c,map,{[{{c,atom,[counters],unknown},optional,{c,map,{[],any,any},unknown}},{{c,atom,[gauges],unknown},optional,{c,map,{[],any,any},unknown}},{{c,atom,[rate],unknown},optional,{c,map,{[],any,any},unknown}},{{c,atom,[slides],unknown},optional,{c,map,{[],any,any},unknown}}],none,none},unknown}],{4,any}}],{2,{c,atom,[ok],unknown}}}]}],unknown},[any]},{emqx_eviction_agent,evict_sessions,3} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},{c,atom,[disabled],unknown}],{2,{c,atom,[error],unknown}}},none,none],unknown},[any,{c,union,[{c,atom,any,unknown},none,none,none,{c,list,{any,{c,nil,[],unknown}},unknown},none,none,none,none],unknown},any]},{emqx_proto_v1,is_running,1} => {any,[{c,atom,any,unknown}]},{emqx_node_rebalance_proto_v1,disable_rebalance_agent,2} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,identifier,[pid],unknown}]},{emqx_ds_proto_v1,next,5} => {any,[{c,atom,any,unknown},{c,atom,any,unknown},{c,binary,{8,0},unknown},{c,opaque,[{opaque,emqx_ds_storage_layer,iterator,0,{c,map,{[{{c,number,{int_set,[1]},integer},mandatory,{c,number,{int_set,[2]},integer}},{{c,number,{int_set,[2]},integer},mandatory,{c,number,{int_rng,0,1114111},integer}},{{c,number,{int_set,[3]},integer},mandatory,any}],none,none},unknown}}],unknown},{c,number,{int_rng,1,pos_inf},integer}]},{emqx_topic_metrics,metrics,0} => {{c,list,{{c,map,{[{{c,atom,[create_time],unknown},mandatory,any},{{c,atom,[metrics],unknown},mandatory,{c,map,{[],any,any},unknown}},{{c,atom,[reset_time],unknown},optional,any},{{c,atom,[topic],unknown},mandatory,any}],none,none},unknown},{c,nil,[],unknown}},unknown},[]},{emqx_node_rebalance_evacuation,start,1} => {any,[{c,map,{[],any,any},unknown}]},{emqx_conf,get_node_and_config,1} => {{c,tuple,[{c,atom,any,unknown},any],{2,any}},[{c,list,{{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,nil,[],unknown}},unknown}]},{emqx_conf_proto_v3,get_override_config_file,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_prometheus,do_start,0} => {{c,atom,[ok],unknown},[]},{emqx_node_rebalance_evacuation,stop,0} => {any,[]},{emqx_mgmt_data_backup,delete_file,1} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,atom,any,unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,binary,{8,0},unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},none,none],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{any,{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},{c,number,{int_rng,0,1114111},integer},none,none,none],unknown},{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},none,none,none,none],unknown}]},{emqx_ft_storage_exporter_fs_proxy,read_export_file_local,2} => {any,[any,any]},{emqx_retainer_proto_v2,active_mnesia_indices,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_node_rebalance_status,rebalance_status,0} => {{c,tuple,[{c,atom,any,unknown},{c,union,[{c,atom,[disabled],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[enabled],unknown},{c,map,{[],any,any},unknown}],{2,{c,atom,[enabled],unknown}}},none,none],unknown}],{2,any}},[]},{emqx_mgmt_cluster_proto_v2,invite_node,2} => {any,[{c,atom,any,unknown},{c,atom,any,unknown}]},{emqx_bridge_proto_v1,lookup_from_all_nodes,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_bridge_proto_v5,restart_bridges_to_all_nodes,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_conf_proto_v2,get_config,3} => {any,[{c,atom,any,unknown},{c,list,{{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,nil,[],unknown}},unknown},any]},{emqx_ft_storage_fs_proto_v1,list_assemblers,2} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,tuple,[{c,binary,{8,0},unknown},{c,binary,{8,0},unknown}],{2,any}}]},{emqx_shared_sub_proto_v1,dispatch_with_ack,5} => {any,[{c,identifier,[pid],unknown},{c,union,[{c,atom,['_'],unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,binary,{8,0},unknown},{c,tuple,[{c,atom,[message],unknown},{c,binary,{8,0},unknown},any,{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,map,{[],{c,atom,any,unknown},{c,atom,[false,true],unknown}},unknown},{c,map,{[{{c,atom,[allow_publish],unknown},optional,{c,atom,[false,true],unknown}},{{c,atom,[peerhost],unknown},optional,{c,tuple_set,[{4,[{c,tuple,[{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer},{c,number,{int_rng,0,255},integer}],{4,any}}]},{8,[{c,tuple,[{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer},{c,number,{int_rng,0,1114111},integer}],{8,any}}]}],unknown}},{{c,atom,[properties],unknown},optional,{c,map,{[],{c,atom,any,unknown},any},unknown}},{{c,atom,[proto_ver],unknown},optional,{c,union,[none,{c,binary,{8,0},unknown},none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none],unknown}},{{c,atom,[protocol],unknown},optional,{c,atom,any,unknown}},{{c,atom,[username],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}}],{c,atom,any,unknown},any},unknown},{c,binary,{8,0},unknown},{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{any,{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},{c,number,{int_rng,0,255},integer},none,none,none],unknown},{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},none,none,none,none],unknown},{c,number,any,integer},any],{10,{c,atom,[message],unknown}}},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none],unknown}]},{emqx_node_rebalance_status,purge_status,0} => {{c,tuple,[{c,atom,any,unknown},{c,union,[{c,atom,[disabled],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[enabled],unknown},{c,map,{[{{c,atom,[current_sessions],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[initial_sessions],unknown},mandatory,{c,number,{int_rng,0,pos_inf},integer}},{{c,atom,[purge_rate],unknown},mandatory,{c,number,{int_rng,1,pos_inf},integer}}],none,none},unknown}],{2,{c,atom,[enabled],unknown}}},none,none],unknown}],{2,any}},[]},{emqx_conf_proto_v1,get_all,1} => {any,[{c,list,{{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,nil,[],unknown}},unknown}]},{emqx_conf_proto_v3,get_all,1} => {any,[{c,list,{{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,nil,[],unknown}},unknown}]},{emqx_node_rebalance_proto_v3,evict_sessions,4} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,number,{int_rng,0,pos_inf},integer},{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,atom,[connected,connecting,disconnected,idle,reauthenticating],unknown}]},{emqx_ft_storage_fs_proxy,pread_local,4} => {any,[any,any,any,any]},{emqx_gateway_cm,do_lookup_by_clientid,2} => {{c,list,{any,{c,nil,[],unknown}},unknown},[{c,union,[{c,atom,any,unknown},none,none,none,{c,list,{{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}},unknown},{c,number,any,unknown},none,none,none],unknown},any]},{emqx_mgmt_api_plugins_proto_v2,delete_package,1} => {any,[{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_telemetry_proto_v1,get_node_uuid,1} => {any,[{c,atom,any,unknown}]},{emqx_node_rebalance_proto_v1,disconnected_session_counts,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_management_proto_v2,get_full_config,1} => {any,[{c,atom,any,unknown}]},{emqx_bridge_proto_v5,get_metrics_from_all_nodes,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_bridge_proto_v4,list_bridges_on_nodes,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_mgmt_trace_proto_v2,trace_file_detail,2} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,union,[{c,atom,any,unknown},none,none,none,{c,list,{any,{c,nil,[],unknown}},unknown},{c,number,{int_rng,0,1114111},integer},none,none,none],unknown},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_mgmt_api_trace,read_trace_file,3} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[eof],unknown},{c,union,[{c,atom,[undefined],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none],unknown}],{2,{c,atom,[eof],unknown}}},{c,tuple,[{c,atom,[error],unknown},{c,union,[{c,atom,any,unknown},none,none,none,none,none,{c,tuple,[{c,atom,[no_translation],unknown},{c,atom,[unicode],unknown},{c,atom,[latin1],unknown}],{3,{c,atom,[no_translation],unknown}}},none,none],unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[ok],unknown},{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,1114111},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}],{2,{c,atom,[ok],unknown}}}]}],unknown},[{c,binary,{8,0},unknown},any,any]},{emqx_connector_resource,start,2} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},none,none],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{any,{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},{c,number,{int_rng,0,255},integer},none,none,none],unknown},{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{any,{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},{c,number,{int_rng,0,255},integer},none,none,none],unknown},{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},none,none,none,none],unknown}]},{emqx_exhook_mgr,server_info,1} => {any,[any]},{emqx_retainer_proto_v2,wait_dispatch_complete,2} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,[infinity],unknown},none,none,none,none,{c,number,{int_rng,0,pos_inf},integer},none,none,none],unknown}]},{emqx_gateway_cm,do_get_chann_conn_mod,3} => {any,[any,any,any]},{emqx_node_rebalance_status_proto_v1,evacuation_status,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_bridge_v2,list,0} => {any,[]},{emqx_node_rebalance_proto_v3,evict_connections,2} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,number,{int_rng,0,pos_inf},integer}]},{emqx_node_rebalance,stop,0} => {any,[]},{emqx_mgmt_api_cluster,connected_replicants,0} => {{c,list,{{c,tuple,[{c,atom,any,unknown},{c,atom,any,unknown},{c,identifier,[pid],unknown}],{3,any}},{c,nil,[],unknown}},unknown},[]},{emqx_bridge_proto_v3,restart_bridge_to_node,3} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_management_proto_v4,kickout_clients,2} => {any,[{c,atom,any,unknown},{c,list,{{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,nil,[],unknown}},unknown}]},{emqx_license_proto_v2,remote_connection_counts,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_bridge_proto_v1,stop_bridges_to_all_nodes,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_proto_v1,clean_pem_cache,1} => {any,[{c,atom,any,unknown}]},{emqx_persistent_session_ds_proto_v1,close_all_iterators,2} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,binary,{8,0},unknown}]},{emqx_mgmt_api_plugins,install_package,2} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},{c,map,{[],any,any},unknown}],{2,{c,atom,[error],unknown}}},none,none],unknown},[{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{{c,union,[none,none,none,none,{c,list,{any,{c,nil,[],unknown}},unknown},{c,number,{int_rng,0,1114111},integer},none,none,none],unknown},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,list,{any,{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},{c,number,{int_rng,0,255},integer},none,none,none],unknown},{c,union,[none,{c,binary,{8,0},unknown},none,none,{c,nil,[],unknown},none,none,none,none],unknown}},unknown},none,none,none,none],unknown}]},{emqx_node_rebalance_proto_v2,disable_rebalance_agent,3} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,identifier,[pid],unknown},any]},{emqx_bridge_v2,start,2} => {{c,union,[{c,atom,[ok],unknown},none,none,none,none,none,{c,tuple,[{c,atom,[error],unknown},any],{2,{c,atom,[error],unknown}}},none,none],unknown},[{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,{c,list,{{c,number,{int_rng,0,255},integer},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}]},{emqx_gateway_cm_proto_v1,kick_session,4} => {any,[{c,atom,any,unknown},{c,atom,[discard,kick],unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown}]},{emqx_node_rebalance_api_proto_v1,node_rebalance_evacuation_start,2} => {any,[{c,atom,any,unknown},{c,map,{[{{c,atom,[conn_evict_rate],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[migrate_to],unknown},optional,{c,union,[{c,atom,[undefined],unknown},none,none,none,{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},none,none,none,none],unknown}},{{c,atom,[server_reference],unknown},optional,{c,union,[{c,atom,[undefined],unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}},{{c,atom,[sess_evict_rate],unknown},optional,{c,number,{int_rng,1,pos_inf},integer}},{{c,atom,[wait_health_check],unknown},optional,{c,number,any,unknown}},{{c,atom,[wait_takeover],unknown},optional,{c,number,any,unknown}}],none,none},unknown}]},{emqx_exhook_proto_v1,server_info,2} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,binary,{8,0},unknown}]},{emqx_conf_proto_v1,get_override_config_file,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_node_rebalance_proto_v3,session_counts,1} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown}]},{emqx_delayed_proto_v2,delete_delayed_message,2} => {any,[{c,atom,any,unknown},{c,binary,{8,0},unknown}]},{emqx_topic_metrics_proto_v1,metrics,2} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,binary,{8,0},unknown}]},{emqx_proto_v2,deactivate_alarm,2} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown}]},{emqx_gateway_cm_proto_v1,set_chan_stats,4} => {any,[{c,atom,any,unknown},{c,union,[{c,atom,any,unknown},{c,binary,{8,0},unknown},none,none,none,none,none,none,none],unknown},{c,identifier,[pid],unknown},{c,list,{{c,tuple,[{c,atom,any,unknown},any],{2,any}},{c,nil,[],unknown}},unknown}]},{emqx_mgmt_cluster_proto_v1,invite_node,2} => {any,[{c,atom,any,unknown},{c,atom,any,unknown}]},{emqx_gateway_http_proto_v1,get_cluster_status,2} => {any,[{c,list,{{c,atom,any,unknown},{c,nil,[],unknown}},unknown},{c,atom,any,unknown}]},{emqx_mgmt,do_unsubscribe_batch,2} => {{c,tuple_set,[{2,[{c,tuple,[{c,atom,[error],unknown},{c,atom,[channel_not_found],unknown}],{2,{c,atom,[error],unknown}}},{c,tuple,[{c,atom,[unsubscribe],unknown},{c,list,{{c,tuple,[any,any],{2,any}},{c,nil,[],unknown}},unknown}],{2,{c,atom,[unsubscribe],unknown}}}]}],unknown},[any,any]},{emqx_mgmt_api_plugins_proto_v1,get_plugins,0} => {any,[]}}}. diff --git a/apps/emqx/test/emqx_sup_SUITE.erl b/apps/emqx/test/emqx_sup_SUITE.erl index d2780469e..7a2461c20 100644 --- a/apps/emqx/test/emqx_sup_SUITE.erl +++ b/apps/emqx/test/emqx_sup_SUITE.erl @@ -24,12 +24,11 @@ all() -> emqx_common_test_helpers:all(?MODULE). init_per_suite(Config) -> - emqx_common_test_helpers:boot_modules(all), - emqx_common_test_helpers:start_apps([]), - Config. + Apps = emqx_cth_suite:start([emqx], #{work_dir => emqx_cth_suite:work_dir(Config)}), + [{apps, Apps} | Config]. -end_per_suite(_Config) -> - emqx_common_test_helpers:stop_apps([]). +end_per_suite(Config) -> + emqx_cth_suite:stop(proplists:get_value(apps, Config)). t_child(_) -> ?assertMatch({error, _}, emqx_sup:start_child(undef, worker)), diff --git a/apps/emqx_auth/src/emqx_auth.app.src b/apps/emqx_auth/src/emqx_auth.app.src index 0135876a6..769929cc9 100644 --- a/apps/emqx_auth/src/emqx_auth.app.src +++ b/apps/emqx_auth/src/emqx_auth.app.src @@ -1,7 +1,7 @@ %% -*- mode: erlang -*- {application, emqx_auth, [ {description, "EMQX Authentication and authorization"}, - {vsn, "0.2.0"}, + {vsn, "0.2.1"}, {modules, []}, {registered, [emqx_auth_sup]}, {applications, [ diff --git a/apps/emqx_auth/src/emqx_authz/emqx_authz.erl b/apps/emqx_auth/src/emqx_authz/emqx_authz.erl index 80fdd4f2d..5bc5e88df 100644 --- a/apps/emqx_auth/src/emqx_authz/emqx_authz.erl +++ b/apps/emqx_auth/src/emqx_authz/emqx_authz.erl @@ -408,8 +408,7 @@ init_metrics(Source) -> {stop, #{result => deny, from => ?MODULE}}. authorize_deny( #{ - username := Username, - peerhost := IpAddress + username := Username } = _Client, _PubSub, Topic, @@ -419,13 +418,15 @@ authorize_deny( ?SLOG(warning, #{ msg => "authorization_not_initialized", username => Username, - ipaddr => IpAddress, topic => Topic, source => ?MODULE }), {stop, #{result => deny, from => ?MODULE}}. -%% @doc Check AuthZ +%% @doc Check AuthZ. +%% DefaultResult is always ignored in this callback because the final decision +%% is to be made by `emqx_access_control' module after all authorization +%% sources are exhausted. -spec authorize( emqx_types:clientinfo(), emqx_types:pubsub(), @@ -434,77 +435,36 @@ authorize_deny( sources() ) -> authz_result(). -authorize( - #{ - username := Username, - peerhost := IpAddress - } = Client, - PubSub, - Topic, - DefaultResult, - Sources -) -> +authorize(Client, PubSub, Topic, _DefaultResult, Sources) -> case maps:get(is_superuser, Client, false) of true -> - log_allowed(#{ - username => Username, - ipaddr => IpAddress, - topic => Topic, - is_superuser => true - }), emqx_metrics:inc(?METRIC_SUPERUSER), {stop, #{result => allow, from => superuser}}; false -> - authorize_non_superuser(Client, PubSub, Topic, DefaultResult, Sources) + authorize_non_superuser(Client, PubSub, Topic, Sources) end. -authorize_non_superuser( - #{ - username := Username, - peerhost := IpAddress - } = Client, - PubSub, - Topic, - _DefaultResult, - Sources -) -> +authorize_non_superuser(Client, PubSub, Topic, Sources) -> case do_authorize(Client, PubSub, Topic, sources_with_defaults(Sources)) of {{matched, allow}, AuthzSource} -> - log_allowed(#{ - username => Username, - ipaddr => IpAddress, - topic => Topic, - source => AuthzSource - }), emqx_metrics_worker:inc(authz_metrics, AuthzSource, allow), emqx_metrics:inc(?METRIC_ALLOW), - {stop, #{result => allow, from => AuthzSource}}; + {stop, #{result => allow, from => source_for_logging(AuthzSource, Client)}}; {{matched, deny}, AuthzSource} -> - ?SLOG(warning, #{ - msg => "authorization_permission_denied", - username => Username, - ipaddr => IpAddress, - topic => Topic, - source => AuthzSource - }), emqx_metrics_worker:inc(authz_metrics, AuthzSource, deny), emqx_metrics:inc(?METRIC_DENY), - {stop, #{result => deny, from => AuthzSource}}; + {stop, #{result => deny, from => source_for_logging(AuthzSource, Client)}}; nomatch -> ?tp(authz_non_superuser, #{result => nomatch}), - ?SLOG(info, #{ - msg => "authorization_failed_nomatch", - username => Username, - ipaddr => IpAddress, - topic => Topic, - reason => "no-match rule" - }), emqx_metrics:inc(?METRIC_NOMATCH), + %% return ignore here because there might be other hook callbacks ignore end. -log_allowed(Meta) -> - ?SLOG(info, Meta#{msg => "authorization_permission_allowed"}). +source_for_logging(client_info, #{acl := Acl}) -> + maps:get(source_for_logging, Acl, client_info); +source_for_logging(Type, _) -> + Type. do_authorize(_Client, _PubSub, _Topic, []) -> nomatch; @@ -512,8 +472,7 @@ do_authorize(Client, PubSub, Topic, [#{enable := false} | Rest]) -> do_authorize(Client, PubSub, Topic, Rest); do_authorize( #{ - username := Username, - peerhost := IpAddress + username := Username } = Client, PubSub, Topic, @@ -527,9 +486,8 @@ do_authorize( ?TRACE("AUTHZ", "authorization_module_nomatch", #{ module => Module, username => Username, - ipaddr => IpAddress, topic => Topic, - pub_sub => PubSub + action => emqx_access_control:format_action(PubSub) }), do_authorize(Client, PubSub, Topic, Tail); %% {matched, allow | deny | ignore} @@ -537,18 +495,16 @@ do_authorize( ?TRACE("AUTHZ", "authorization_module_match_ignore", #{ module => Module, username => Username, - ipaddr => IpAddress, topic => Topic, - pub_sub => PubSub + action => emqx_access_control:format_action(PubSub) }), do_authorize(Client, PubSub, Topic, Tail); ignore -> ?TRACE("AUTHZ", "authorization_module_ignore", #{ module => Module, username => Username, - ipaddr => IpAddress, topic => Topic, - pub_sub => PubSub + action => emqx_access_control:format_action(PubSub) }), do_authorize(Client, PubSub, Topic, Tail); %% {matched, allow | deny} diff --git a/apps/emqx_auth/src/emqx_authz/emqx_authz_rule.erl b/apps/emqx_auth/src/emqx_authz/emqx_authz_rule.erl index eba0ee554..9fac4f7f0 100644 --- a/apps/emqx_auth/src/emqx_authz/emqx_authz_rule.erl +++ b/apps/emqx_auth/src/emqx_authz/emqx_authz_rule.erl @@ -106,9 +106,15 @@ compile({Permission, Who, Action, TopicFilters}) when || Topic <- TopicFilters ]}; compile({Permission, _Who, _Action, _TopicFilter}) when not ?IS_PERMISSION(Permission) -> - throw({invalid_authorization_permission, Permission}); + throw(#{ + reason => invalid_authorization_permission, + value => Permission + }); compile(BadRule) -> - throw({invalid_authorization_rule, BadRule}). + throw(#{ + reason => invalid_authorization_rule, + value => BadRule + }). compile_action(Action) -> compile_action(emqx_authz:feature_available(rich_actions), Action). @@ -133,7 +139,10 @@ compile_action(true = _RichActionsOn, {Action, Opts}) when retain => retain_from_opts(Opts) }; compile_action(_RichActionsOn, Action) -> - throw({invalid_authorization_action, Action}). + throw(#{ + reason => invalid_authorization_action, + value => Action + }). qos_from_opts(Opts) -> try @@ -152,20 +161,29 @@ qos_from_opts(Opts) -> ) end catch - bad_qos -> - throw({invalid_authorization_qos, Opts}) + {bad_qos, QoS} -> + throw(#{ + reason => invalid_authorization_qos, + qos => QoS + }) end. validate_qos(QoS) when is_integer(QoS), QoS >= 0, QoS =< 2 -> QoS; -validate_qos(_) -> - throw(bad_qos). +validate_qos(QoS) -> + throw({bad_qos, QoS}). retain_from_opts(Opts) -> case proplists:get_value(retain, Opts, ?DEFAULT_RULE_RETAIN) of - all -> all; - Retain when is_boolean(Retain) -> Retain; - _ -> throw({invalid_authorization_retain, Opts}) + all -> + all; + Retain when is_boolean(Retain) -> + Retain; + Value -> + throw(#{ + reason => invalid_authorization_retain, + value => Value + }) end. compile_who(all) -> @@ -193,7 +211,10 @@ compile_who({'and', L}) when is_list(L) -> compile_who({'or', L}) when is_list(L) -> {'or', [compile_who(Who) || Who <- L]}; compile_who(Who) -> - throw({invalid_who, Who}). + throw(#{ + reason => invalid_client_match_condition, + identifier => Who + }). compile_topic("eq " ++ Topic) -> {eq, emqx_topic:words(bin(Topic))}; @@ -254,9 +275,17 @@ match_action(#{action_type := subscribe, qos := QoS}, #{action_type := subscribe match_qos(QoS, QoSCond); match_action(#{action_type := subscribe, qos := QoS}, #{action_type := all, qos := QoSCond}) -> match_qos(QoS, QoSCond); -match_action(_, _) -> +match_action(_, PubSubCond) -> + true = is_pubsub_cond(PubSubCond), false. +is_pubsub_cond(publish) -> + true; +is_pubsub_cond(subscribe) -> + true; +is_pubsub_cond(#{action_type := A}) -> + is_pubsub_cond(A). + match_pubsub(publish, publish) -> true; match_pubsub(subscribe, subscribe) -> true; match_pubsub(_, all) -> true; diff --git a/apps/emqx_auth/src/emqx_authz/emqx_authz_rule_raw.erl b/apps/emqx_auth/src/emqx_authz/emqx_authz_rule_raw.erl index 1fbe2ca45..701c06e30 100644 --- a/apps/emqx_auth/src/emqx_authz/emqx_authz_rule_raw.erl +++ b/apps/emqx_auth/src/emqx_authz/emqx_authz_rule_raw.erl @@ -37,7 +37,7 @@ emqx_authz_rule:action_condition(), emqx_authz_rule:topic_condition() }} - | {error, term()}. + | {error, map()}. parse_rule( #{ <<"permission">> := PermissionRaw, @@ -51,11 +51,18 @@ parse_rule( Action = validate_rule_action(ActionType, RuleRaw), {ok, {Permission, Action, Topics}} catch - throw:ValidationError -> - {error, ValidationError} + throw:{Invalid, Which} -> + {error, #{ + reason => Invalid, + value => Which + }} end; parse_rule(RuleRaw) -> - {error, {invalid_rule, RuleRaw}}. + {error, #{ + reason => invalid_rule, + value => RuleRaw, + explain => "missing 'permission' or 'action' field" + }}. -spec format_rule({ emqx_authz_rule:permission(), @@ -88,7 +95,7 @@ validate_rule_topics(#{<<"topic">> := TopicRaw}) when is_binary(TopicRaw) -> validate_rule_topics(#{<<"topics">> := TopicsRaw}) when is_list(TopicsRaw) -> lists:map(fun validate_rule_topic/1, TopicsRaw); validate_rule_topics(RuleRaw) -> - throw({invalid_topics, RuleRaw}). + throw({missing_topic_or_topics, RuleRaw}). validate_rule_topic(<<"eq ", TopicRaw/binary>>) -> {eq, validate_rule_topic(TopicRaw)}; @@ -98,8 +105,8 @@ validate_rule_permission(<<"allow">>) -> allow; validate_rule_permission(<<"deny">>) -> deny; validate_rule_permission(PermissionRaw) -> throw({invalid_permission, PermissionRaw}). -validate_rule_action_type(<<"publish">>) -> publish; -validate_rule_action_type(<<"subscribe">>) -> subscribe; +validate_rule_action_type(P) when P =:= <<"pub">> orelse P =:= <<"publish">> -> publish; +validate_rule_action_type(S) when S =:= <<"sub">> orelse S =:= <<"subscribe">> -> subscribe; validate_rule_action_type(<<"all">>) -> all; validate_rule_action_type(ActionRaw) -> throw({invalid_action, ActionRaw}). @@ -152,7 +159,7 @@ validate_rule_qos_atomic(<<"2">>) -> 2; validate_rule_qos_atomic(0) -> 0; validate_rule_qos_atomic(1) -> 1; validate_rule_qos_atomic(2) -> 2; -validate_rule_qos_atomic(_) -> throw(invalid_qos). +validate_rule_qos_atomic(QoS) -> throw({invalid_qos, QoS}). validate_rule_retain(<<"0">>) -> false; validate_rule_retain(<<"1">>) -> true; diff --git a/apps/emqx_auth/src/emqx_authz/sources/emqx_authz_client_info.erl b/apps/emqx_auth/src/emqx_authz/sources/emqx_authz_client_info.erl index ae8360943..e77d36713 100644 --- a/apps/emqx_auth/src/emqx_authz/sources/emqx_authz_client_info.erl +++ b/apps/emqx_auth/src/emqx_authz/sources/emqx_authz_client_info.erl @@ -34,6 +34,10 @@ authorize/4 ]). +-define(IS_V1(Rules), is_map(Rules)). +-define(IS_V2(Rules), is_list(Rules)). + +%% For v1 -define(RULE_NAMES, [ {[pub, <<"pub">>], publish}, {[sub, <<"sub">>], subscribe}, @@ -55,10 +59,46 @@ update(Source) -> destroy(_Source) -> ok. +%% @doc Authorize based on cllientinfo enriched with `acl' data. +%% e.g. From JWT. +%% +%% Supproted rules formats are: +%% +%% v1: (always deny when no match) +%% +%% #{ +%% pub => [TopicFilter], +%% sub => [TopicFilter], +%% all => [TopicFilter] +%% } +%% +%% v2: (rules are checked in sequence, passthrough when no match) +%% +%% [{ +%% Permission :: emqx_authz_rule:permission(), +%% Action :: emqx_authz_rule:action_condition(), +%% Topics :: emqx_authz_rule:topic_condition() +%% }] +%% +%% which is compiled from raw rules like below by emqx_authz_rule_raw +%% +%% [ +%% #{ +%% permission := allow | deny +%% action := pub | sub | all +%% topic => TopicFilter, +%% topics => [TopicFilter] %% when 'topic' is not provided +%% qos => 0 | 1 | 2 | [0, 1, 2] +%% retain => true | false | all %% only for pub action +%% } +%% ] +%% authorize(#{acl := Acl} = Client, PubSub, Topic, _Source) -> case check(Acl) of - {ok, Rules} when is_map(Rules) -> - do_authorize(Client, PubSub, Topic, Rules); + {ok, Rules} when ?IS_V2(Rules) -> + authorize_v2(Client, PubSub, Topic, Rules); + {ok, Rules} when ?IS_V1(Rules) -> + authorize_v1(Client, PubSub, Topic, Rules); {error, MatchResult} -> MatchResult end; @@ -69,7 +109,7 @@ authorize(_Client, _PubSub, _Topic, _Source) -> %% Internal functions %%-------------------------------------------------------------------- -check(#{expire := Expire, rules := Rules}) when is_map(Rules) -> +check(#{expire := Expire, rules := Rules}) -> Now = erlang:system_time(second), case Expire of N when is_integer(N) andalso N > Now -> {ok, Rules}; @@ -83,13 +123,13 @@ check(#{rules := Rules}) -> check(#{}) -> {error, nomatch}. -do_authorize(Client, PubSub, Topic, AclRules) -> - do_authorize(Client, PubSub, Topic, AclRules, ?RULE_NAMES). +authorize_v1(Client, PubSub, Topic, AclRules) -> + authorize_v1(Client, PubSub, Topic, AclRules, ?RULE_NAMES). -do_authorize(_Client, _PubSub, _Topic, _AclRules, []) -> +authorize_v1(_Client, _PubSub, _Topic, _AclRules, []) -> {matched, deny}; -do_authorize(Client, PubSub, Topic, AclRules, [{Keys, Action} | RuleNames]) -> - TopicFilters = get_topic_filters(Keys, AclRules, []), +authorize_v1(Client, PubSub, Topic, AclRules, [{Keys, Action} | RuleNames]) -> + TopicFilters = get_topic_filters_v1(Keys, AclRules, []), case emqx_authz_rule:match( Client, @@ -99,13 +139,16 @@ do_authorize(Client, PubSub, Topic, AclRules, [{Keys, Action} | RuleNames]) -> ) of {matched, Permission} -> {matched, Permission}; - nomatch -> do_authorize(Client, PubSub, Topic, AclRules, RuleNames) + nomatch -> authorize_v1(Client, PubSub, Topic, AclRules, RuleNames) end. -get_topic_filters([], _Rules, Default) -> +get_topic_filters_v1([], _Rules, Default) -> Default; -get_topic_filters([Key | Keys], Rules, Default) -> +get_topic_filters_v1([Key | Keys], Rules, Default) -> case Rules of #{Key := Value} -> Value; - #{} -> get_topic_filters(Keys, Rules, Default) + #{} -> get_topic_filters_v1(Keys, Rules, Default) end. + +authorize_v2(Client, PubSub, Topic, Rules) -> + emqx_authz_rule:matches(Client, PubSub, Topic, Rules). diff --git a/apps/emqx_auth/test/emqx_authz/emqx_authz_SUITE.erl b/apps/emqx_auth/test/emqx_authz/emqx_authz_SUITE.erl index 37c9ebfc1..e0ef906ad 100644 --- a/apps/emqx_auth/test/emqx_authz/emqx_authz_SUITE.erl +++ b/apps/emqx_auth/test/emqx_authz/emqx_authz_SUITE.erl @@ -178,11 +178,13 @@ t_bad_file_source(_) -> BadContent = ?SOURCE_FILE(<<"{allow,{username,\"bar\"}, publish, [\"test\"]}">>), BadContentErr = {bad_acl_file_content, {1, erl_parse, ["syntax error before: ", []]}}, BadRule = ?SOURCE_FILE(<<"{allow,{username,\"bar\"},publish}.">>), - BadRuleErr = {invalid_authorization_rule, {allow, {username, "bar"}, publish}}, + BadRuleErr = #{ + reason => invalid_authorization_rule, value => {allow, {username, "bar"}, publish} + }, BadPermission = ?SOURCE_FILE(<<"{not_allow,{username,\"bar\"},publish,[\"test\"]}.">>), - BadPermissionErr = {invalid_authorization_permission, not_allow}, + BadPermissionErr = #{reason => invalid_authorization_permission, value => not_allow}, BadAction = ?SOURCE_FILE(<<"{allow,{username,\"bar\"},pubsub,[\"test\"]}.">>), - BadActionErr = {invalid_authorization_action, pubsub}, + BadActionErr = #{reason => invalid_authorization_action, value => pubsub}, lists:foreach( fun({Source, Error}) -> File = emqx_authz_file:acl_conf_file(), diff --git a/apps/emqx_auth/test/emqx_authz/emqx_authz_file_SUITE.erl b/apps/emqx_auth/test/emqx_authz/emqx_authz_file_SUITE.erl index af5a8affc..5728c2d96 100644 --- a/apps/emqx_auth/test/emqx_authz/emqx_authz_file_SUITE.erl +++ b/apps/emqx_auth/test/emqx_authz/emqx_authz_file_SUITE.erl @@ -100,7 +100,7 @@ t_rich_actions(_Config) -> t_no_rich_actions(_Config) -> _ = emqx_authz:set_feature_available(rich_actions, false), ?assertMatch( - {error, {pre_config_update, emqx_authz, {invalid_authorization_action, _}}}, + {error, {pre_config_update, emqx_authz, #{reason := invalid_authorization_action}}}, emqx_authz:update(?CMD_REPLACE, [ ?RAW_SOURCE#{ <<"rules">> => diff --git a/apps/emqx_auth/test/emqx_authz/emqx_authz_rule_SUITE.erl b/apps/emqx_auth/test/emqx_authz/emqx_authz_rule_SUITE.erl index d81a93038..1f759b28f 100644 --- a/apps/emqx_auth/test/emqx_authz/emqx_authz_rule_SUITE.erl +++ b/apps/emqx_auth/test/emqx_authz/emqx_authz_rule_SUITE.erl @@ -176,7 +176,7 @@ t_compile_ce(_Config) -> _ = emqx_authz:set_feature_available(rich_actions, false), ?assertThrow( - {invalid_authorization_action, _}, + #{reason := invalid_authorization_action}, emqx_authz_rule:compile( {allow, {username, "test"}, {all, [{qos, 2}, {retain, true}]}, ["topic/test"]} ) @@ -676,34 +676,34 @@ t_match(_) -> t_invalid_rule(_) -> ?assertThrow( - {invalid_authorization_permission, _}, + #{reason := invalid_authorization_permission}, emqx_authz_rule:compile({allawww, all, all, ["topic/test"]}) ), ?assertThrow( - {invalid_authorization_rule, _}, + #{reason := invalid_authorization_rule}, emqx_authz_rule:compile(ooops) ), ?assertThrow( - {invalid_authorization_qos, _}, + #{reason := invalid_authorization_qos}, emqx_authz_rule:compile({allow, {username, "test"}, {publish, [{qos, 3}]}, ["topic/test"]}) ), ?assertThrow( - {invalid_authorization_retain, _}, + #{reason := invalid_authorization_retain}, emqx_authz_rule:compile( {allow, {username, "test"}, {publish, [{retain, 'FALSE'}]}, ["topic/test"]} ) ), ?assertThrow( - {invalid_authorization_action, _}, + #{reason := invalid_authorization_action}, emqx_authz_rule:compile({allow, all, unsubscribe, ["topic/test"]}) ), ?assertThrow( - {invalid_who, _}, + #{reason := invalid_client_match_condition}, emqx_authz_rule:compile({allow, who, all, ["topic/test"]}) ). diff --git a/apps/emqx_auth_jwt/src/emqx_auth_jwt.app.src b/apps/emqx_auth_jwt/src/emqx_auth_jwt.app.src index b4b5ccf02..7e313881e 100644 --- a/apps/emqx_auth_jwt/src/emqx_auth_jwt.app.src +++ b/apps/emqx_auth_jwt/src/emqx_auth_jwt.app.src @@ -1,7 +1,7 @@ %% -*- mode: erlang -*- {application, emqx_auth_jwt, [ {description, "EMQX JWT Authentication and Authorization"}, - {vsn, "0.1.1"}, + {vsn, "0.2.0"}, {registered, []}, {mod, {emqx_auth_jwt_app, []}}, {applications, [ diff --git a/apps/emqx_auth_jwt/src/emqx_authn_jwt.erl b/apps/emqx_auth_jwt/src/emqx_authn_jwt.erl index 5e83a0d13..768d8e4be 100644 --- a/apps/emqx_auth_jwt/src/emqx_authn_jwt.erl +++ b/apps/emqx_auth_jwt/src/emqx_authn_jwt.erl @@ -219,14 +219,24 @@ verify(undefined, _, _, _) -> verify(JWT, JWKs, VerifyClaims, AclClaimName) -> case do_verify(JWT, JWKs, VerifyClaims) of {ok, Extra} -> - {ok, acl(Extra, AclClaimName)}; + try + {ok, acl(Extra, AclClaimName)} + catch + throw:{bad_acl_rule, Reason} -> + %% it's a invalid token, so ok to log + ?TRACE_AUTHN_PROVIDER("bad_acl_rule", Reason#{jwt => JWT}), + {error, bad_username_or_password} + end; {error, {missing_claim, Claim}} -> + %% it's a invalid token, so it's ok to log ?TRACE_AUTHN_PROVIDER("missing_jwt_claim", #{jwt => JWT, claim => Claim}), {error, bad_username_or_password}; {error, invalid_signature} -> + %% it's a invalid token, so it's ok to log ?TRACE_AUTHN_PROVIDER("invalid_jwt_signature", #{jwks => JWKs, jwt => JWT}), ignore; {error, {claims, Claims}} -> + %% it's a invalid token, so it's ok to log ?TRACE_AUTHN_PROVIDER("invalid_jwt_claims", #{jwt => JWT, claims => Claims}), {error, bad_username_or_password} end. @@ -237,7 +247,8 @@ acl(Claims, AclClaimName) -> #{AclClaimName := Rules} -> #{ acl => #{ - rules => Rules, + rules => parse_rules(Rules), + source_for_logging => jwt, expire => maps:get(<<"exp">>, Claims, undefined) } }; @@ -363,3 +374,24 @@ binary_to_number(Bin) -> _ -> false end end. + +%% Pars rules which can be in two different formats: +%% 1. #{<<"pub">> => [<<"a/b">>, <<"c/d">>], <<"sub">> => [...], <<"all">> => [...]} +%% 2. [#{<<"permission">> => <<"allow">>, <<"action">> => <<"publish">>, <<"topic">> => <<"a/b">>}, ...] +parse_rules(Rules) when is_map(Rules) -> + Rules; +parse_rules(Rules) when is_list(Rules) -> + lists:map(fun parse_rule/1, Rules). + +parse_rule(Rule) -> + case emqx_authz_rule_raw:parse_rule(Rule) of + {ok, {Permission, Action, Topics}} -> + try + emqx_authz_rule:compile({Permission, all, Action, Topics}) + catch + throw:Reason -> + throw({bad_acl_rule, Reason}) + end; + {error, Reason} -> + throw({bad_acl_rule, Reason}) + end. diff --git a/apps/emqx_auth_jwt/test/emqx_authz_jwt_SUITE.erl b/apps/emqx_auth_jwt/test/emqx_authz_jwt_SUITE.erl index 4be420202..bd9fc85c1 100644 --- a/apps/emqx_auth_jwt/test/emqx_authz_jwt_SUITE.erl +++ b/apps/emqx_auth_jwt/test/emqx_authz_jwt_SUITE.erl @@ -78,7 +78,7 @@ end_per_testcase(_TestCase, _Config) -> %%------------------------------------------------------------------------------ t_topic_rules(_Config) -> - Payload = #{ + JWT = #{ <<"exp">> => erlang:system_time(second) + 60, <<"acl">> => #{ <<"pub">> => [ @@ -99,7 +99,47 @@ t_topic_rules(_Config) -> }, <<"username">> => <<"username">> }, - JWT = generate_jws(Payload), + test_topic_rules(JWT). + +t_topic_rules_v2(_Config) -> + JWT = #{ + <<"exp">> => erlang:system_time(second) + 60, + <<"acl">> => [ + #{ + <<"permission">> => <<"allow">>, + <<"action">> => <<"pub">>, + <<"topics">> => [ + <<"eq testpub1/${username}">>, + <<"testpub2/${clientid}">>, + <<"testpub3/#">> + ] + }, + #{ + <<"permission">> => <<"allow">>, + <<"action">> => <<"sub">>, + <<"topics">> => + [ + <<"eq testsub1/${username}">>, + <<"testsub2/${clientid}">>, + <<"testsub3/#">> + ] + }, + #{ + <<"permission">> => <<"allow">>, + <<"action">> => <<"all">>, + <<"topics">> => [ + <<"eq testall1/${username}">>, + <<"testall2/${clientid}">>, + <<"testall3/#">> + ] + } + ], + <<"username">> => <<"username">> + }, + test_topic_rules(JWT). + +test_topic_rules(JWTInput) -> + JWT = generate_jws(JWTInput), {ok, C} = emqtt:start_link( [ @@ -350,6 +390,64 @@ t_check_undefined_expire(_Config) -> emqx_authz_client_info:authorize(Client, ?AUTHZ_SUBSCRIBE, <<"a/bar">>, undefined) ). +t_invalid_rule(_Config) -> + emqx_logger:set_log_level(debug), + MakeJWT = fun(Acl) -> + generate_jws(#{ + <<"exp">> => erlang:system_time(second) + 60, + <<"username">> => <<"username">>, + <<"acl">> => Acl + }) + end, + InvalidAclList = + [ + %% missing action + [#{<<"permission">> => <<"invalid">>}], + %% missing topic or topics + [#{<<"permission">> => <<"allow">>, <<"action">> => <<"pub">>}], + %% invlaid permission, must be allow | deny + [ + #{ + <<"permission">> => <<"invalid">>, + <<"action">> => <<"pub">>, + <<"topic">> => <<"t">> + } + ], + %% invalid action, must be pub | sub | all + [ + #{ + <<"permission">> => <<"allow">>, + <<"action">> => <<"invalid">>, + <<"topic">> => <<"t">> + } + ], + %% invalid qos + [ + #{ + <<"permission">> => <<"allow">>, + <<"action">> => <<"pub">>, + <<"topics">> => [<<"t">>], + <<"qos">> => 3 + } + ] + ], + lists:foreach( + fun(InvalidAcl) -> + {ok, C} = emqtt:start_link( + [ + {clean_start, true}, + {proto_ver, v5}, + {clientid, <<"clientid">>}, + {username, <<"username">>}, + {password, MakeJWT(InvalidAcl)} + ] + ), + unlink(C), + ?assertMatch({error, {bad_username_or_password, _}}, emqtt:connect(C)) + end, + InvalidAclList + ). + %%------------------------------------------------------------------------------ %% Helpers %%------------------------------------------------------------------------------ diff --git a/apps/emqx_auth_mnesia/test/emqx_authz_mnesia_SUITE.erl b/apps/emqx_auth_mnesia/test/emqx_authz_mnesia_SUITE.erl index 7d77116e0..dfc273cd0 100644 --- a/apps/emqx_auth_mnesia/test/emqx_authz_mnesia_SUITE.erl +++ b/apps/emqx_auth_mnesia/test/emqx_authz_mnesia_SUITE.erl @@ -190,7 +190,7 @@ t_normalize_rules(_Config) -> ?assertException( error, - {invalid_rule, _}, + #{reason := invalid_rule}, emqx_authz_mnesia:store_rules( {username, <<"username">>}, [[<<"allow">>, <<"publish">>, <<"t">>]] @@ -199,16 +199,22 @@ t_normalize_rules(_Config) -> ?assertException( error, - {invalid_action, _}, + #{reason := invalid_action}, emqx_authz_mnesia:store_rules( {username, <<"username">>}, - [#{<<"permission">> => <<"allow">>, <<"action">> => <<"pub">>, <<"topic">> => <<"t">>}] + [ + #{ + <<"permission">> => <<"allow">>, + <<"action">> => <<"badaction">>, + <<"topic">> => <<"t">> + } + ] ) ), ?assertException( error, - {invalid_permission, _}, + #{reason := invalid_permission}, emqx_authz_mnesia:store_rules( {username, <<"username">>}, [ diff --git a/apps/emqx_bridge_azure_event_hub/rebar.config b/apps/emqx_bridge_azure_event_hub/rebar.config index 90be538b3..6169ef8ea 100644 --- a/apps/emqx_bridge_azure_event_hub/rebar.config +++ b/apps/emqx_bridge_azure_event_hub/rebar.config @@ -1,6 +1,6 @@ %% -*- mode: erlang; -*- {erl_opts, [debug_info]}. -{deps, [ {wolff, {git, "https://github.com/kafka4beam/wolff.git", {tag, "1.8.0"}}} +{deps, [ {wolff, {git, "https://github.com/kafka4beam/wolff.git", {tag, "1.9.1"}}} , {kafka_protocol, {git, "https://github.com/kafka4beam/kafka_protocol.git", {tag, "4.1.3"}}} , {brod_gssapi, {git, "https://github.com/kafka4beam/brod_gssapi.git", {tag, "v0.1.1"}}} , {brod, {git, "https://github.com/kafka4beam/brod.git", {tag, "3.16.8"}}} diff --git a/apps/emqx_bridge_confluent/rebar.config b/apps/emqx_bridge_confluent/rebar.config index 0c0c2eece..4f700e4cd 100644 --- a/apps/emqx_bridge_confluent/rebar.config +++ b/apps/emqx_bridge_confluent/rebar.config @@ -1,6 +1,6 @@ %% -*- mode: erlang; -*- {erl_opts, [debug_info]}. -{deps, [ {wolff, {git, "https://github.com/kafka4beam/wolff.git", {tag, "1.8.0"}}} +{deps, [ {wolff, {git, "https://github.com/kafka4beam/wolff.git", {tag, "1.9.1"}}} , {kafka_protocol, {git, "https://github.com/kafka4beam/kafka_protocol.git", {tag, "4.1.3"}}} , {brod_gssapi, {git, "https://github.com/kafka4beam/brod_gssapi.git", {tag, "v0.1.1"}}} , {brod, {git, "https://github.com/kafka4beam/brod.git", {tag, "3.16.8"}}} diff --git a/apps/emqx_bridge_dynamo/rebar.config b/apps/emqx_bridge_dynamo/rebar.config index e80fb0f80..38598d313 100644 --- a/apps/emqx_bridge_dynamo/rebar.config +++ b/apps/emqx_bridge_dynamo/rebar.config @@ -1,6 +1,6 @@ %% -*- mode: erlang; -*- {erl_opts, [debug_info]}. -{deps, [ {erlcloud, {git, "https://github.com/emqx/erlcloud", {tag, "3.7.0-emqx-2"}}} +{deps, [ {erlcloud, {git, "https://github.com/emqx/erlcloud", {tag, "3.7.0.3"}}} , {emqx_connector, {path, "../../apps/emqx_connector"}} , {emqx_resource, {path, "../../apps/emqx_resource"}} , {emqx_bridge, {path, "../../apps/emqx_bridge"}} diff --git a/apps/emqx_bridge_gcp_pubsub/src/emqx_bridge_gcp_pubsub.app.src b/apps/emqx_bridge_gcp_pubsub/src/emqx_bridge_gcp_pubsub.app.src index 9b7558923..c4a814da9 100644 --- a/apps/emqx_bridge_gcp_pubsub/src/emqx_bridge_gcp_pubsub.app.src +++ b/apps/emqx_bridge_gcp_pubsub/src/emqx_bridge_gcp_pubsub.app.src @@ -1,6 +1,6 @@ {application, emqx_bridge_gcp_pubsub, [ {description, "EMQX Enterprise GCP Pub/Sub Bridge"}, - {vsn, "0.2.0"}, + {vsn, "0.2.1"}, {registered, []}, {applications, [ kernel, diff --git a/apps/emqx_bridge_gcp_pubsub/src/emqx_bridge_gcp_pubsub_client.erl b/apps/emqx_bridge_gcp_pubsub/src/emqx_bridge_gcp_pubsub_client.erl index 5975ba89b..7091bbf8f 100644 --- a/apps/emqx_bridge_gcp_pubsub/src/emqx_bridge_gcp_pubsub_client.erl +++ b/apps/emqx_bridge_gcp_pubsub/src/emqx_bridge_gcp_pubsub_client.erl @@ -428,7 +428,8 @@ do_get_status(ResourceId, Timeout) -> msg => "ehttpc_health_check_failed", connector => ResourceId, reason => Reason, - worker => Worker + worker => Worker, + wait_time => Timeout }), false end diff --git a/apps/emqx_bridge_gcp_pubsub/test/emqx_bridge_gcp_pubsub_producer_SUITE.erl b/apps/emqx_bridge_gcp_pubsub/test/emqx_bridge_gcp_pubsub_producer_SUITE.erl index f65b80f90..d68e2bcfc 100644 --- a/apps/emqx_bridge_gcp_pubsub/test/emqx_bridge_gcp_pubsub_producer_SUITE.erl +++ b/apps/emqx_bridge_gcp_pubsub/test/emqx_bridge_gcp_pubsub_producer_SUITE.erl @@ -310,7 +310,7 @@ gcp_pubsub_config(Config) -> io_lib:format( "bridges.gcp_pubsub.~s {\n" " enable = true\n" - " connect_timeout = 1s\n" + " connect_timeout = 5s\n" " service_account_json = ~s\n" " payload_template = ~p\n" " pubsub_topic = ~s\n" @@ -1404,8 +1404,23 @@ t_failure_no_body(Config) -> ), ok. +kill_gun_process(EhttpcPid) -> + State = ehttpc:get_state(EhttpcPid, minimal), + GunPid = maps:get(client, State), + true = is_pid(GunPid), + _ = exit(GunPid, kill), + ok. + +kill_gun_processes(ConnectorResourceId) -> + Pool = ehttpc:workers(ConnectorResourceId), + Workers = lists:map(fun({_, Pid}) -> Pid end, Pool), + %% assert there is at least one pool member + ?assertMatch([_ | _], Workers), + lists:foreach(fun(Pid) -> kill_gun_process(Pid) end, Workers). + t_unrecoverable_error(Config) -> ActionResourceId = ?config(action_resource_id, Config), + ConnectorResourceId = ?config(connector_resource_id, Config), TelemetryTable = ?config(telemetry_table, Config), TestPid = self(), FailureNoBodyHandler = @@ -1415,10 +1430,7 @@ t_unrecoverable_error(Config) -> %% kill the gun process while it's waiting for the %% response so we provoke an `{error, _}' response from %% ehttpc. - lists:foreach( - fun(Pid) -> exit(Pid, kill) end, - [Pid || {_, Pid, _, _} <- supervisor:which_children(gun_sup)] - ), + ok = kill_gun_processes(ConnectorResourceId), Rep = cowboy_req:reply( 200, #{<<"content-type">> => <<"application/json">>}, @@ -1531,7 +1543,7 @@ t_get_status_down(Config) -> t_get_status_timeout_calling_workers(Config) -> ResourceId = ?config(connector_resource_id, Config), - {ok, _} = create_bridge(Config), + {ok, _} = create_bridge(Config, #{<<"connect_timeout">> => <<"1s">>}), emqx_common_test_helpers:with_mock( ehttpc, health_check, diff --git a/apps/emqx_bridge_greptimedb/rebar.config b/apps/emqx_bridge_greptimedb/rebar.config index f0942f910..985299c3d 100644 --- a/apps/emqx_bridge_greptimedb/rebar.config +++ b/apps/emqx_bridge_greptimedb/rebar.config @@ -6,7 +6,7 @@ {emqx_connector, {path, "../../apps/emqx_connector"}}, {emqx_resource, {path, "../../apps/emqx_resource"}}, {emqx_bridge, {path, "../../apps/emqx_bridge"}}, - {greptimedb, {git, "https://github.com/GreptimeTeam/greptimedb-client-erl", {tag, "v0.1.2"}}} + {greptimedb, {git, "https://github.com/GreptimeTeam/greptimedb-client-erl", {tag, "v0.1.6"}}} ]}. {plugins, [rebar3_path_deps]}. {project_plugins, [erlfmt]}. diff --git a/apps/emqx_bridge_greptimedb/src/emqx_bridge_greptimedb.app.src b/apps/emqx_bridge_greptimedb/src/emqx_bridge_greptimedb.app.src index 71a6656fa..0875d13ba 100644 --- a/apps/emqx_bridge_greptimedb/src/emqx_bridge_greptimedb.app.src +++ b/apps/emqx_bridge_greptimedb/src/emqx_bridge_greptimedb.app.src @@ -1,6 +1,6 @@ {application, emqx_bridge_greptimedb, [ {description, "EMQX GreptimeDB Bridge"}, - {vsn, "0.1.6"}, + {vsn, "0.1.7"}, {registered, []}, {applications, [ kernel, diff --git a/apps/emqx_bridge_greptimedb/src/emqx_bridge_greptimedb_connector.erl b/apps/emqx_bridge_greptimedb/src/emqx_bridge_greptimedb_connector.erl index d588f7f8c..af42dac52 100644 --- a/apps/emqx_bridge_greptimedb/src/emqx_bridge_greptimedb_connector.erl +++ b/apps/emqx_bridge_greptimedb/src/emqx_bridge_greptimedb_connector.erl @@ -21,8 +21,11 @@ on_stop/2, on_query/3, on_batch_query/3, + on_query_async/4, + on_batch_query_async/4, on_get_status/2 ]). +-export([reply_callback/2]). -export([ roots/0, @@ -57,7 +60,7 @@ %% ------------------------------------------------------------------------------------------------- %% resource callback -callback_mode() -> always_sync. +callback_mode() -> async_if_possible. on_start(InstId, Config) -> %% InstID as pool would be handled by greptimedb client @@ -110,6 +113,49 @@ on_batch_query(InstId, BatchData, _State = #{write_syntax := SyntaxLines, client {error, {unrecoverable_error, Reason}} end. +on_query_async( + InstId, + {send_message, Data}, + {ReplyFun, Args}, + _State = #{write_syntax := SyntaxLines, client := Client} +) -> + case data_to_points(Data, SyntaxLines) of + {ok, Points} -> + ?tp( + greptimedb_connector_send_query, + #{points => Points, batch => false, mode => async} + ), + do_async_query(InstId, Client, Points, {ReplyFun, Args}); + {error, ErrorPoints} = Err -> + ?tp( + greptimedb_connector_send_query_error, + #{batch => false, mode => async, error => ErrorPoints} + ), + log_error_points(InstId, ErrorPoints), + Err + end. + +on_batch_query_async( + InstId, + BatchData, + {ReplyFun, Args}, + #{write_syntax := SyntaxLines, client := Client} +) -> + case parse_batch_data(InstId, BatchData, SyntaxLines) of + {ok, Points} -> + ?tp( + greptimedb_connector_send_query, + #{points => Points, batch => true, mode => async} + ), + do_async_query(InstId, Client, Points, {ReplyFun, Args}); + {error, Reason} -> + ?tp( + greptimedb_connector_send_query_error, + #{batch => true, mode => async, error => Reason} + ), + {error, {unrecoverable_error, Reason}} + end. + on_get_status(_InstId, #{client := Client}) -> case greptimedb:is_alive(Client) of true -> @@ -344,6 +390,31 @@ do_query(InstId, Client, Points) -> end end. +do_async_query(InstId, Client, Points, ReplyFunAndArgs) -> + ?SLOG(info, #{ + msg => "greptimedb_write_point_async", + connector => InstId, + points => Points + }), + WrappedReplyFunAndArgs = {fun ?MODULE:reply_callback/2, [ReplyFunAndArgs]}, + ok = greptimedb:async_write_batch(Client, Points, WrappedReplyFunAndArgs). + +reply_callback(ReplyFunAndArgs, {error, {unauth, _, _}}) -> + ?tp(greptimedb_connector_do_query_failure, #{error => <<"authorization failure">>}), + Result = {error, {unrecoverable_error, <<"authorization failure">>}}, + emqx_resource:apply_reply_fun(ReplyFunAndArgs, Result); +reply_callback(ReplyFunAndArgs, {error, Reason} = Error) -> + case is_unrecoverable_error(Error) of + true -> + Result = {error, {unrecoverable_error, Reason}}, + emqx_resource:apply_reply_fun(ReplyFunAndArgs, Result); + false -> + Result = {error, {recoverable_error, Reason}}, + emqx_resource:apply_reply_fun(ReplyFunAndArgs, Result) + end; +reply_callback(ReplyFunAndArgs, Result) -> + emqx_resource:apply_reply_fun(ReplyFunAndArgs, Result). + %% ------------------------------------------------------------------------------------------------- %% Tags & Fields Config Trans diff --git a/apps/emqx_bridge_greptimedb/test/emqx_bridge_greptimedb_SUITE.erl b/apps/emqx_bridge_greptimedb/test/emqx_bridge_greptimedb_SUITE.erl index f9d8854ac..73223892d 100644 --- a/apps/emqx_bridge_greptimedb/test/emqx_bridge_greptimedb_SUITE.erl +++ b/apps/emqx_bridge_greptimedb/test/emqx_bridge_greptimedb_SUITE.erl @@ -25,16 +25,23 @@ groups() -> TCs = emqx_common_test_helpers:all(?MODULE), [ {with_batch, [ - {group, sync_query} + {group, sync_query}, + {group, async_query} ]}, {without_batch, [ - {group, sync_query} + {group, sync_query}, + {group, async_query} ]}, {sync_query, [ {group, grpcv1_tcp} %% uncomment tls when we are ready %% {group, grpcv1_tls} ]}, + {async_query, [ + {group, grpcv1_tcp} + %% uncomment tls when we are ready + %% {group, grpcv1_tls} + ]}, {grpcv1_tcp, TCs} %%{grpcv1_tls, TCs} ]. @@ -130,6 +137,8 @@ init_per_group(GreptimedbType, Config0) when end; init_per_group(sync_query, Config) -> [{query_mode, sync} | Config]; +init_per_group(async_query, Config) -> + [{query_mode, async} | Config]; init_per_group(with_batch, Config) -> [{batch_size, 100} | Config]; init_per_group(without_batch, Config) -> @@ -420,6 +429,9 @@ t_start_ok(Config) -> ?check_trace( begin case QueryMode of + async -> + ?assertMatch(ok, send_message(Config, SentData)), + ct:sleep(500); sync -> ?assertMatch({ok, _}, send_message(Config, SentData)) end, @@ -666,6 +678,9 @@ t_const_timestamp(Config) -> <<"timestamp">> => erlang:system_time(millisecond) }, case QueryMode of + async -> + ?assertMatch(ok, send_message(Config, SentData)), + ct:sleep(500); sync -> ?assertMatch({ok, _}, send_message(Config, SentData)) end, @@ -709,9 +724,12 @@ t_boolean_variants(Config) -> }, case QueryMode of sync -> - ?assertMatch({ok, _}, send_message(Config, SentData)) + ?assertMatch({ok, _}, send_message(Config, SentData)); + async -> + ?assertMatch(ok, send_message(Config, SentData)) end, case QueryMode of + async -> ct:sleep(500); sync -> ok end, PersistedData = query_by_clientid(atom_to_binary(?FUNCTION_NAME), ClientId, Config), @@ -779,11 +797,29 @@ t_bad_timestamp(Config) -> #{?snk_kind := greptimedb_connector_send_query_error}, 10_000 ), - fun(Result, _Trace) -> + fun(Result, Trace) -> ?assertMatch({_, {ok, _}}, Result), {Return, {ok, _}} = Result, IsBatch = BatchSize > 1, case {QueryMode, IsBatch} of + {async, true} -> + ?assertEqual(ok, Return), + ?assertMatch( + [#{error := points_trans_failed}], + ?of_kind(greptimedb_connector_send_query_error, Trace) + ); + {async, false} -> + ?assertEqual(ok, Return), + ?assertMatch( + [ + #{ + error := [ + {error, {bad_timestamp, <<"bad_timestamp">>}} + ] + } + ], + ?of_kind(greptimedb_connector_send_query_error, Trace) + ); {sync, false} -> ?assertEqual( {error, [ @@ -907,17 +943,34 @@ t_write_failure(Config) -> {error, {resource_error, #{reason := timeout}}}, send_message(Config, SentData) ), - #{?snk_kind := greptimedb_connector_do_query_failure, action := nack}, - 16_000 + #{?snk_kind := handle_async_reply, action := nack}, + 1_000 + ); + async -> + ?wait_async_action( + ?assertEqual(ok, send_message(Config, SentData)), + #{?snk_kind := handle_async_reply}, + 1_000 ) end end), - fun(Trace) -> + fun(Trace0) -> case QueryMode of sync -> - ?assertMatch( - [#{error := _} | _], - ?of_kind(greptimedb_connector_do_query_failure, Trace) + Trace = ?of_kind(handle_async_reply, Trace0), + ?assertMatch([_ | _], Trace), + [#{result := Result} | _] = Trace, + ?assert( + not emqx_bridge_greptimedb_connector:is_unrecoverable_error(Result), + #{got => Result} + ); + async -> + Trace = ?of_kind(handle_async_reply, Trace0), + ?assertMatch([_ | _], Trace), + [#{result := Result} | _] = Trace, + ?assert( + not emqx_bridge_greptimedb_connector:is_unrecoverable_error(Result), + #{got => Result} ) end, ok @@ -1029,6 +1082,23 @@ t_authentication_error_on_send_message(Config0) -> ?assertMatch( {error, {unrecoverable_error, <<"authorization failure">>}}, send_message(Config, SentData) + ); + async -> + ?check_trace( + begin + ?wait_async_action( + ?assertEqual(ok, send_message(Config, SentData)), + #{?snk_kind := handle_async_reply}, + 1_000 + ) + end, + fun(Trace) -> + ?assertMatch( + [#{error := <<"authorization failure">>} | _], + ?of_kind(greptimedb_connector_do_query_failure, Trace) + ), + ok + end ) end, ok. diff --git a/apps/emqx_bridge_http/src/emqx_bridge_http.app.src b/apps/emqx_bridge_http/src/emqx_bridge_http.app.src index a7f8688d4..c03a15b01 100644 --- a/apps/emqx_bridge_http/src/emqx_bridge_http.app.src +++ b/apps/emqx_bridge_http/src/emqx_bridge_http.app.src @@ -1,6 +1,6 @@ {application, emqx_bridge_http, [ {description, "EMQX HTTP Bridge and Connector Application"}, - {vsn, "0.2.0"}, + {vsn, "0.2.1"}, {registered, []}, {applications, [kernel, stdlib, emqx_connector, emqx_resource, ehttpc]}, {env, [{emqx_action_info_modules, [emqx_bridge_http_action_info]}]}, diff --git a/apps/emqx_bridge_http/src/emqx_bridge_http_connector.erl b/apps/emqx_bridge_http/src/emqx_bridge_http_connector.erl index 1777fbe1f..51375fc04 100644 --- a/apps/emqx_bridge_http/src/emqx_bridge_http_connector.erl +++ b/apps/emqx_bridge_http/src/emqx_bridge_http_connector.erl @@ -205,7 +205,9 @@ on_start( http -> {tcp, []}; https -> - SSLOpts = emqx_tls_lib:to_client_opts(maps:get(ssl, Config)), + SSLConf = maps:get(ssl, Config), + %% force enable ssl + SSLOpts = emqx_tls_lib:to_client_opts(SSLConf#{enable => true}), {tls, SSLOpts} end, NTransportOpts = emqx_utils:ipv6_probe(TransportOpts), diff --git a/apps/emqx_bridge_influxdb/test/emqx_bridge_influxdb_connector_SUITE.erl b/apps/emqx_bridge_influxdb/test/emqx_bridge_influxdb_connector_SUITE.erl index 9aec94b65..94e8e3fad 100644 --- a/apps/emqx_bridge_influxdb/test/emqx_bridge_influxdb_connector_SUITE.erl +++ b/apps/emqx_bridge_influxdb/test/emqx_bridge_influxdb_connector_SUITE.erl @@ -124,7 +124,7 @@ perform_lifecycle_check(PoolName, InitialConfig) -> ?assertEqual({error, not_found}, emqx_resource:get_instance(PoolName)). t_tls_verify_none(Config) -> - PoolName = <<"emqx_bridge_influxdb_connector_SUITE">>, + PoolName = <<"testpool-1">>, Host = ?config(influxdb_tls_host, Config), Port = ?config(influxdb_tls_port, Config), InitialConfig = influxdb_config(Host, Port, true, <<"verify_none">>), @@ -135,7 +135,7 @@ t_tls_verify_none(Config) -> ok. t_tls_verify_peer(Config) -> - PoolName = <<"emqx_bridge_influxdb_connector_SUITE">>, + PoolName = <<"testpool-2">>, Host = ?config(influxdb_tls_host, Config), Port = ?config(influxdb_tls_port, Config), InitialConfig = influxdb_config(Host, Port, true, <<"verify_peer">>), @@ -157,7 +157,11 @@ perform_tls_opts_check(PoolName, InitialConfig, VerifyReturn) -> to_client_opts, fun(Opts) -> Verify = {verify_fun, {custom_verify(), {return, VerifyReturn}}}, - [Verify | meck:passthrough([Opts])] + [ + Verify, + {cacerts, public_key:cacerts_get()} + | meck:passthrough([Opts]) + ] end ), try diff --git a/apps/emqx_bridge_kafka/rebar.config b/apps/emqx_bridge_kafka/rebar.config index b69ec1262..db7d619e1 100644 --- a/apps/emqx_bridge_kafka/rebar.config +++ b/apps/emqx_bridge_kafka/rebar.config @@ -1,6 +1,6 @@ %% -*- mode: erlang; -*- {erl_opts, [debug_info]}. -{deps, [ {wolff, {git, "https://github.com/kafka4beam/wolff.git", {tag, "1.8.0"}}} +{deps, [ {wolff, {git, "https://github.com/kafka4beam/wolff.git", {tag, "1.9.1"}}} , {kafka_protocol, {git, "https://github.com/kafka4beam/kafka_protocol.git", {tag, "4.1.3"}}} , {brod_gssapi, {git, "https://github.com/kafka4beam/brod_gssapi.git", {tag, "v0.1.1"}}} , {brod, {git, "https://github.com/kafka4beam/brod.git", {tag, "3.16.8"}}} diff --git a/apps/emqx_bridge_kafka/src/emqx_bridge_kafka.app.src b/apps/emqx_bridge_kafka/src/emqx_bridge_kafka.app.src index f5fb12432..ffdb7eb20 100644 --- a/apps/emqx_bridge_kafka/src/emqx_bridge_kafka.app.src +++ b/apps/emqx_bridge_kafka/src/emqx_bridge_kafka.app.src @@ -1,7 +1,7 @@ %% -*- mode: erlang -*- {application, emqx_bridge_kafka, [ {description, "EMQX Enterprise Kafka Bridge"}, - {vsn, "0.2.0"}, + {vsn, "0.2.1"}, {registered, [emqx_bridge_kafka_consumer_sup]}, {applications, [ kernel, diff --git a/apps/emqx_bridge_kafka/src/emqx_bridge_kafka_impl_producer.erl b/apps/emqx_bridge_kafka/src/emqx_bridge_kafka_impl_producer.erl index bf8c76bee..7caab1d87 100644 --- a/apps/emqx_bridge_kafka/src/emqx_bridge_kafka_impl_producer.erl +++ b/apps/emqx_bridge_kafka/src/emqx_bridge_kafka_impl_producer.erl @@ -539,7 +539,7 @@ check_topic_and_leader_connections(ClientId, KafkaTopic) -> kafka_client => ClientId, kafka_topic => KafkaTopic }); - {error, restarting} -> + {error, client_supervisor_not_initialized} -> throw(#{ reason => restarting, kafka_client => ClientId, @@ -620,16 +620,19 @@ producers_config(BridgeType, BridgeName, Input, IsDryRun, BridgeV2Id) -> partition_count_refresh_interval := PCntRefreshInterval, max_inflight := MaxInflight, buffer := #{ - mode := BufferMode, + mode := BufferMode0, per_partition_limit := PerPartitionLimit, segment_bytes := SegmentBytes, - memory_overload_protection := MemOLP0 + memory_overload_protection := MemOLP } } = Input, - MemOLP = - case os:type() of - {unix, linux} -> MemOLP0; - _ -> false + %% avoid creating dirs for probing producers + BufferMode = + case IsDryRun of + true -> + memory; + false -> + BufferMode0 end, {OffloadMode, ReplayqDir} = case BufferMode of @@ -638,7 +641,6 @@ producers_config(BridgeType, BridgeName, Input, IsDryRun, BridgeV2Id) -> hybrid -> {true, replayq_dir(BridgeType, BridgeName)} end, #{ - name => make_producer_name(BridgeType, BridgeName, IsDryRun), partitioner => partitioner(PartitionStrategy), partition_count_refresh_interval_seconds => PCntRefreshInterval, replayq_dir => ReplayqDir, @@ -669,18 +671,6 @@ replayq_dir(BridgeType, BridgeName) -> ]), filename:join([emqx:data_dir(), "kafka", DirName]). -%% Producer name must be an atom which will be used as a ETS table name for -%% partition worker lookup. -make_producer_name(_BridgeType, _BridgeName, true = _IsDryRun) -> - %% It is a dry run and we don't want to leak too many atoms - %% so we use the default producer name instead of creating - %% an unique name. - probing_wolff_producers; -make_producer_name(BridgeType, BridgeName, _IsDryRun) -> - %% Woff needs an atom for ets table name registration. The assumption here is - %% that bridges with new names are not often created. - binary_to_atom(iolist_to_binary([BridgeType, "_", bin(BridgeName)])). - with_log_at_error(Fun, Log) -> try Fun() diff --git a/apps/emqx_bridge_kinesis/rebar.config b/apps/emqx_bridge_kinesis/rebar.config index e4b57846e..4d7f87540 100644 --- a/apps/emqx_bridge_kinesis/rebar.config +++ b/apps/emqx_bridge_kinesis/rebar.config @@ -1,6 +1,6 @@ %% -*- mode: erlang; -*- {erl_opts, [debug_info]}. -{deps, [ {erlcloud, {git, "https://github.com/emqx/erlcloud", {tag, "3.7.0-emqx-2"}}} +{deps, [ {erlcloud, {git, "https://github.com/emqx/erlcloud", {tag, "3.7.0.3"}}} , {emqx_connector, {path, "../../apps/emqx_connector"}} , {emqx_resource, {path, "../../apps/emqx_resource"}} , {emqx_bridge, {path, "../../apps/emqx_bridge"}} diff --git a/apps/emqx_bridge_mqtt/test/emqx_bridge_mqtt_SUITE.erl b/apps/emqx_bridge_mqtt/test/emqx_bridge_mqtt_SUITE.erl index bde546bd0..7490ad054 100644 --- a/apps/emqx_bridge_mqtt/test/emqx_bridge_mqtt_SUITE.erl +++ b/apps/emqx_bridge_mqtt/test/emqx_bridge_mqtt_SUITE.erl @@ -230,19 +230,18 @@ t_conf_bridge_authn_passfile(Config) -> ?assertReceive( {authenticate, #{username := Username2, password := Password2}} ), - ?assertMatch( - {ok, 201, #{ - <<"status">> := <<"disconnected">>, - <<"status_reason">> := <<"#{msg => failed_to_read_secret_file", _/bytes>> - }}, + {ok, 201, #{ + <<"status">> := <<"disconnected">>, + <<"status_reason">> := Reason + }} = request_json( post, uri(["bridges"]), ?SERVER_CONF(<<>>, <<"file://im/pretty/sure/theres/no/such/file">>)#{ <<"name">> => <<"t_conf_bridge_authn_no_passfile">> } - ) - ). + ), + ?assertMatch({match, _}, re:run(Reason, <<"failed_to_read_secret_file">>)). hook_authenticate() -> emqx_hooks:add('client.authenticate', {?MODULE, authenticate, [self()]}, ?HP_HIGHEST). diff --git a/apps/emqx_bridge_pulsar/test/emqx_bridge_pulsar_impl_producer_SUITE.erl b/apps/emqx_bridge_pulsar/test/emqx_bridge_pulsar_impl_producer_SUITE.erl index 6b5bc2896..185e278b3 100644 --- a/apps/emqx_bridge_pulsar/test/emqx_bridge_pulsar_impl_producer_SUITE.erl +++ b/apps/emqx_bridge_pulsar/test/emqx_bridge_pulsar_impl_producer_SUITE.erl @@ -385,7 +385,6 @@ start_consumer(TestCase, Config) -> <> ), - ConnOpts = #{}, ConsumerClientId = list_to_atom( atom_to_list(TestCase) ++ integer_to_list(erlang:unique_integer()) ), @@ -396,15 +395,9 @@ start_consumer(TestCase, Config) -> certfile => filename:join([CertsPath, "cert.pem"]), cacertfile => filename:join([CertsPath, "cacert.pem"]) }, - {ok, _ClientPid} = pulsar:ensure_supervised_client( - ConsumerClientId, - [URL], - #{ - conn_opts => ConnOpts, - ssl_opts => emqx_tls_lib:to_client_opts(SSLOpts) - } - ), - ConsumerOpts = #{ + Opts = #{enable_ssl => UseTLS, ssl_opts => emqx_tls_lib:to_client_opts(SSLOpts)}, + {ok, _ClientPid} = pulsar:ensure_supervised_client(ConsumerClientId, [URL], Opts), + ConsumerOpts = Opts#{ cb_init_args => #{send_to => self()}, cb_module => pulsar_echo_consumer, sub_type => 'Shared', @@ -414,8 +407,7 @@ start_consumer(TestCase, Config) -> %% id, or else weird bugs will happen, like the %% consumer never starts... name => list_to_atom("test_consumer" ++ integer_to_list(erlang:unique_integer())), - consumer_id => 1, - conn_opts => ConnOpts + consumer_id => 1 }, {ok, Consumer} = pulsar:ensure_supervised_consumers( ConsumerClientId, diff --git a/apps/emqx_bridge_rabbitmq/rebar.config b/apps/emqx_bridge_rabbitmq/rebar.config index 3f1c5d3fc..010c01e4e 100644 --- a/apps/emqx_bridge_rabbitmq/rebar.config +++ b/apps/emqx_bridge_rabbitmq/rebar.config @@ -4,7 +4,7 @@ %% The following two are dependencies of rabbit_common {thoas, {git, "https://github.com/emqx/thoas.git", {tag, "v1.0.0"}}} , {credentials_obfuscation, {git, "https://github.com/emqx/credentials-obfuscation.git", {tag, "v3.2.0"}}} - %% The v3.11.13_with_app_src tag, employed in the next two dependencies, + %% The v3.11.13.2 (v3.11.13_with_app_src branch), employed in the next two dependencies, %% represents a fork of the official RabbitMQ v3.11.13 tag. This fork diverges %% from the official version as it includes app and hrl files %% generated by make files in subdirectories deps/rabbit_common and @@ -17,11 +17,11 @@ %% packages that we don't have control over. , {rabbit_common, {git_subdir, "https://github.com/emqx/rabbitmq-server.git", - {tag, "v3.11.13-emqx"}, + {tag, "v3.11.13.2"}, "deps/rabbit_common"}} , {amqp_client, {git_subdir, "https://github.com/emqx/rabbitmq-server.git", - {tag, "v3.11.13-emqx"}, + {tag, "v3.11.13.2"}, "deps/amqp_client"}} , {emqx_connector, {path, "../../apps/emqx_connector"}} , {emqx_resource, {path, "../../apps/emqx_resource"}} diff --git a/apps/emqx_connector/test/emqx_connector_jwt_worker_SUITE.erl b/apps/emqx_connector/test/emqx_connector_jwt_worker_SUITE.erl index fdeb980d4..99c36e8ff 100644 --- a/apps/emqx_connector/test/emqx_connector_jwt_worker_SUITE.erl +++ b/apps/emqx_connector/test/emqx_connector_jwt_worker_SUITE.erl @@ -308,7 +308,7 @@ t_lookup_badarg(_Config) -> ok. t_start_supervised_worker(_Config) -> - {ok, _} = emqx_connector_jwt_sup:start_link(), + {ok, Sup} = emqx_connector_jwt_sup:start_link(), Config = #{resource_id := ResourceId, table := TId} = generate_config(), {ok, Pid} = emqx_connector_jwt_sup:ensure_worker_present(ResourceId, Config), Ref = emqx_connector_jwt_worker:ensure_jwt(Pid), @@ -333,7 +333,7 @@ t_start_supervised_worker(_Config) -> ?assertEqual({error, not_found}, emqx_connector_jwt:lookup_jwt(TId, ResourceId)), %% ensure the specs are removed from the supervision tree. ?assertEqual([], supervisor:which_children(emqx_connector_jwt_sup)), - ok. + ok = stop_jwt_sup(Sup). t_start_supervised_worker_already_started(_Config) -> {ok, _} = emqx_connector_jwt_sup:start_link(), @@ -344,17 +344,28 @@ t_start_supervised_worker_already_started(_Config) -> ok. t_start_supervised_worker_already_present(_Config) -> - {ok, _} = emqx_connector_jwt_sup:start_link(), + {ok, Sup} = emqx_connector_jwt_sup:start_link(), Config = #{resource_id := ResourceId} = generate_config(), {ok, Pid0} = emqx_connector_jwt_sup:ensure_worker_present(ResourceId, Config), Ref = monitor(process, Pid0), exit(Pid0, kill), receive {'DOWN', Ref, process, Pid0, killed} -> ok - after 1_000 -> error(worker_didnt_stop) end, {ok, Pid1} = emqx_connector_jwt_sup:ensure_worker_present(ResourceId, Config), ?assertNotEqual(Pid0, Pid1), + ?assert(is_process_alive(Pid1)), + ok = stop_jwt_sup(Sup). + +stop_jwt_sup(Sup) -> + Ref = monitor(process, Sup), + unlink(Sup), + exit(Sup, shutdown), + receive + {'DOWN', Ref, process, Sup, shutdown} -> ok + after 1000 -> + error(timeout) + end, ok. t_unknown_requests(_Config) -> diff --git a/apps/emqx_dashboard/test/emqx_dashboard_SUITE.erl b/apps/emqx_dashboard/test/emqx_dashboard_SUITE.erl index 7f0dd02de..a11b537d1 100644 --- a/apps/emqx_dashboard/test/emqx_dashboard_SUITE.erl +++ b/apps/emqx_dashboard/test/emqx_dashboard_SUITE.erl @@ -261,9 +261,10 @@ request_dashboard(Method, Url, Auth) -> request_dashboard(Method, Url, QueryParams, Auth) -> Request = {Url ++ "?" ++ QueryParams, [Auth]}, do_request_dashboard(Method, Request). -do_request_dashboard(Method, Request) -> + +do_request_dashboard(Method, {Url, _} = Request) -> ct:pal("Method: ~p, Request: ~p", [Method, Request]), - case httpc:request(Method, Request, [], []) of + case httpc:request(Method, Request, maybe_ssl(Url), []) of {error, socket_closed_remotely} -> {error, socket_closed_remotely}; {ok, {{"HTTP/1.1", Code, _}, _Headers, Return}} when @@ -276,6 +277,9 @@ do_request_dashboard(Method, Request) -> {error, Reason} end. +maybe_ssl("http://" ++ _) -> []; +maybe_ssl("https://" ++ _) -> [{ssl, [{verify, verify_none}]}]. + auth_header_() -> auth_header_(<<"admin">>, <<"public">>). diff --git a/apps/emqx_dashboard/test/emqx_dashboard_https_SUITE.erl b/apps/emqx_dashboard/test/emqx_dashboard_https_SUITE.erl index a09f8fa3b..c46c0ddbd 100644 --- a/apps/emqx_dashboard/test/emqx_dashboard_https_SUITE.erl +++ b/apps/emqx_dashboard/test/emqx_dashboard_https_SUITE.erl @@ -198,8 +198,25 @@ t_verify_cacertfile(_Config) -> VerifyPeerConf1, naive_env_interpolation(<<"${EMQX_ETC_DIR}/certs/cacert.pem">>) ), - validate_https(VerifyPeerConf2, MaxConnection, DefaultSSLCert, verify_peer), - ok. + %% we always test client with verify_none and no client cert is sent + %% since the server is configured with verify_peer + %% hence the expected observation on the client side is an error + ErrorReason = + try + validate_https(VerifyPeerConf2, MaxConnection, DefaultSSLCert, verify_peer) + catch + error:{https_client_error, Reason} -> + Reason + end, + %% There seems to be a race-condition causing the return value to vary a bit + case ErrorReason of + socket_closed_remotely -> + ok; + {ssl_error, _SslSock, {tls_alert, {certificate_required, _}}} -> + ok; + Other -> + throw({unexpected, Other}) + end. t_bad_certfile(_Config) -> Conf = #{ @@ -219,9 +236,12 @@ t_bad_certfile(_Config) -> validate_https(Conf, MaxConnection, SSLCert, Verify) -> emqx_common_test_helpers:load_config(emqx_dashboard_schema, Conf), emqx_mgmt_api_test_util:init_suite([emqx_management], fun(X) -> X end), - assert_ranch_options(MaxConnection, SSLCert, Verify), - assert_https_request(), - emqx_mgmt_api_test_util:end_suite([emqx_management]). + try + assert_ranch_options(MaxConnection, SSLCert, Verify), + assert_https_request() + after + emqx_mgmt_api_test_util:end_suite([emqx_management]) + end. assert_ranch_options(MaxConnections0, SSLCert, Verify) -> Middlewares = [emqx_dashboard_middleware, cowboy_router, cowboy_handler], @@ -286,10 +306,10 @@ assert_https_request() -> lists:foreach( fun(Path) -> ApiPath = https_api_path([Path]), - ?assertMatch( - {ok, _}, - emqx_dashboard_SUITE:request_dashboard(get, ApiPath, Headers) - ) + case emqx_dashboard_SUITE:request_dashboard(get, ApiPath, Headers) of + {ok, _} -> ok; + {error, Reason} -> error({https_client_error, Reason}) + end end, ?OVERVIEWS ). diff --git a/apps/emqx_durable_storage/src/emqx_ds.erl b/apps/emqx_durable_storage/src/emqx_ds.erl index 1d18c5d73..aedd5cea0 100644 --- a/apps/emqx_durable_storage/src/emqx_ds.erl +++ b/apps/emqx_durable_storage/src/emqx_ds.erl @@ -22,13 +22,13 @@ -module(emqx_ds). %% Management API: --export([open_db/2, drop_db/1]). +-export([open_db/2, add_generation/2, add_generation/1, drop_db/1]). %% Message storage API: -export([store_batch/2, store_batch/3]). %% Message replay API: --export([get_streams/3, make_iterator/4, next/3]). +-export([get_streams/3, make_iterator/4, update_iterator/3, next/3]). %% Misc. API: -export([]). @@ -44,6 +44,7 @@ iterator/0, iterator_id/0, message_id/0, + message_key/0, message_store_opts/0, next_result/1, next_result/0, store_batch_result/0, @@ -79,6 +80,8 @@ -type ds_specific_stream() :: term(). +-type message_key() :: binary(). + -type store_batch_result() :: ok | {error, _}. -type make_iterator_result(Iterator) :: {ok, Iterator} | {error, _}. @@ -86,13 +89,13 @@ -type make_iterator_result() :: make_iterator_result(iterator()). -type next_result(Iterator) :: - {ok, Iterator, [emqx_types:message()]} | {ok, end_of_stream} | {error, _}. + {ok, Iterator, [{message_key(), emqx_types:message()}]} | {ok, end_of_stream} | {error, _}. -type next_result() :: next_result(iterator()). %% Timestamp %% Earliest possible timestamp is 0. -%% TODO granularity? Currently, we should always use micro second, as that's the unit we +%% TODO granularity? Currently, we should always use milliseconds, as that's the unit we %% use in emqx_guid. Otherwise, the iterators won't match the message timestamps. -type time() :: non_neg_integer(). @@ -121,6 +124,10 @@ -callback open_db(db(), create_db_opts()) -> ok | {error, _}. +-callback add_generation(db()) -> ok | {error, _}. + +-callback add_generation(db(), create_db_opts()) -> ok | {error, _}. + -callback drop_db(db()) -> ok | {error, _}. -callback store_batch(db(), [emqx_types:message()], message_store_opts()) -> store_batch_result(). @@ -130,6 +137,9 @@ -callback make_iterator(db(), ds_specific_stream(), topic_filter(), time()) -> make_iterator_result(ds_specific_iterator()). +-callback update_iterator(db(), ds_specific_iterator(), message_key()) -> + make_iterator_result(ds_specific_iterator()). + -callback next(db(), Iterator, pos_integer()) -> next_result(Iterator). %%================================================================================ @@ -148,6 +158,14 @@ open_db(DB, Opts = #{backend := Backend}) when Backend =:= builtin orelse Backen persistent_term:put(?persistent_term(DB), Module), ?module(DB):open_db(DB, Opts). +-spec add_generation(db()) -> ok. +add_generation(DB) -> + ?module(DB):add_generation(DB). + +-spec add_generation(db(), create_db_opts()) -> ok. +add_generation(DB, Opts) -> + ?module(DB):add_generation(DB, Opts). + %% @doc TODO: currently if one or a few shards are down, they won't be %% deleted. @@ -200,7 +218,7 @@ store_batch(DB, Msgs) -> %% replay. This function returns stream together with its %% "coordinate": `stream_rank()'. %% -%% Stream rank is a tuple of two integers, let's call them X and Y. If +%% Stream rank is a tuple of two terms, let's call them X and Y. If %% X coordinate of two streams is different, they are independent and %% can be replayed in parallel. If it's the same, then the stream with %% smaller Y coordinate should be replayed first. If Y coordinates are @@ -217,6 +235,11 @@ get_streams(DB, TopicFilter, StartTime) -> make_iterator(DB, Stream, TopicFilter, StartTime) -> ?module(DB):make_iterator(DB, Stream, TopicFilter, StartTime). +-spec update_iterator(db(), iterator(), message_key()) -> + make_iterator_result(). +update_iterator(DB, OldIter, DSKey) -> + ?module(DB):update_iterator(DB, OldIter, DSKey). + -spec next(db(), iterator(), pos_integer()) -> next_result(). next(DB, Iter, BatchSize) -> ?module(DB):next(DB, Iter, BatchSize). diff --git a/apps/emqx_durable_storage/src/emqx_ds_replication_layer.erl b/apps/emqx_durable_storage/src/emqx_ds_replication_layer.erl index a9d904da1..9b5c06bff 100644 --- a/apps/emqx_durable_storage/src/emqx_ds_replication_layer.erl +++ b/apps/emqx_durable_storage/src/emqx_ds_replication_layer.erl @@ -23,10 +23,13 @@ -export([ list_shards/1, open_db/2, + add_generation/1, + add_generation/2, drop_db/1, store_batch/3, get_streams/3, make_iterator/4, + update_iterator/3, next/3 ]). @@ -36,7 +39,9 @@ do_store_batch_v1/4, do_get_streams_v1/4, do_make_iterator_v1/5, - do_next_v1/4 + do_update_iterator_v2/4, + do_next_v1/4, + do_add_generation_v2/1 ]). -export_type([shard_id/0, builtin_db_opts/0, stream/0, iterator/0, message_id/0, batch/0]). @@ -119,6 +124,16 @@ open_db(DB, CreateOpts) -> MyShards ). +-spec add_generation(emqx_ds:db()) -> ok | {error, _}. +add_generation(DB) -> + Nodes = emqx_ds_replication_layer_meta:leader_nodes(DB), + _ = emqx_ds_proto_v2:add_generation(Nodes, DB), + ok. + +-spec add_generation(emqx_ds:db(), builtin_db_opts()) -> ok | {error, _}. +add_generation(DB, CreateOpts) -> + emqx_ds_replication_layer_meta:update_db_config(DB, CreateOpts). + -spec drop_db(emqx_ds:db()) -> ok | {error, _}. drop_db(DB) -> Nodes = list_nodes(), @@ -170,6 +185,30 @@ make_iterator(DB, Stream, TopicFilter, StartTime) -> Err end. +-spec update_iterator( + emqx_ds:db(), + iterator(), + emqx_ds:message_key() +) -> + emqx_ds:make_iterator_result(iterator()). +update_iterator(DB, OldIter, DSKey) -> + #{?tag := ?IT, ?shard := Shard, ?enc := StorageIter} = OldIter, + Node = node_of_shard(DB, Shard), + case + emqx_ds_proto_v2:update_iterator( + Node, + DB, + Shard, + StorageIter, + DSKey + ) + of + {ok, Iter} -> + {ok, #{?tag => ?IT, ?shard => Shard, ?enc => Iter}}; + Err = {error, _} -> + Err + end. + -spec next(emqx_ds:db(), iterator(), pos_integer()) -> emqx_ds:next_result(iterator()). next(DB, Iter0, BatchSize) -> #{?tag := ?IT, ?shard := Shard, ?enc := StorageIter0} = Iter0, @@ -236,6 +275,18 @@ do_get_streams_v1(DB, Shard, TopicFilter, StartTime) -> do_make_iterator_v1(DB, Shard, Stream, TopicFilter, StartTime) -> emqx_ds_storage_layer:make_iterator({DB, Shard}, Stream, TopicFilter, StartTime). +-spec do_update_iterator_v2( + emqx_ds:db(), + emqx_ds_replication_layer:shard_id(), + emqx_ds_storage_layer:iterator(), + emqx_ds:message_key() +) -> + emqx_ds:make_iterator_result(emqx_ds_storage_layer:iterator()). +do_update_iterator_v2(DB, Shard, OldIter, DSKey) -> + emqx_ds_storage_layer:update_iterator( + {DB, Shard}, OldIter, DSKey + ). + -spec do_next_v1( emqx_ds:db(), emqx_ds_replication_layer:shard_id(), @@ -246,6 +297,17 @@ do_make_iterator_v1(DB, Shard, Stream, TopicFilter, StartTime) -> do_next_v1(DB, Shard, Iter, BatchSize) -> emqx_ds_storage_layer:next({DB, Shard}, Iter, BatchSize). +-spec do_add_generation_v2(emqx_ds:db()) -> ok | {error, _}. +do_add_generation_v2(DB) -> + MyShards = emqx_ds_replication_layer_meta:my_owned_shards(DB), + + lists:foreach( + fun(ShardId) -> + emqx_ds_storage_layer:add_generation({DB, ShardId}) + end, + MyShards + ). + %%================================================================================ %% Internal functions %%================================================================================ diff --git a/apps/emqx_durable_storage/src/emqx_ds_replication_layer_meta.erl b/apps/emqx_durable_storage/src/emqx_ds_replication_layer_meta.erl index a2fc9dbbf..38c2dbbe7 100644 --- a/apps/emqx_durable_storage/src/emqx_ds_replication_layer_meta.erl +++ b/apps/emqx_durable_storage/src/emqx_ds_replication_layer_meta.erl @@ -21,20 +21,26 @@ %% implementation details from this module. -module(emqx_ds_replication_layer_meta). +-compile(inline). + -behaviour(gen_server). %% API: -export([ shards/1, my_shards/1, + my_owned_shards/1, + leader_nodes/1, replica_set/2, in_sync_replicas/2, sites/0, open_db/2, + update_db_config/2, drop_db/1, shard_leader/2, this_site/0, set_leader/3, + is_leader/1, print_status/0 ]). @@ -44,16 +50,19 @@ %% internal exports: -export([ open_db_trans/2, + update_db_config_trans/2, drop_db_trans/1, claim_site/2, in_sync_replicas_trans/2, set_leader_trans/3, + is_leader_trans/1, n_shards/1 ]). -export_type([site/0]). -include_lib("stdlib/include/qlc.hrl"). +-include_lib("stdlib/include/ms_transform.hrl"). %%================================================================================ %% Type declarations @@ -145,22 +154,34 @@ start_link() -> -spec shards(emqx_ds:db()) -> [emqx_ds_replication_layer:shard_id()]. shards(DB) -> - eval_qlc( - qlc:q([Shard || #?SHARD_TAB{shard = {D, Shard}} <- mnesia:table(?SHARD_TAB), D =:= DB]) - ). + filter_shards(DB). -spec my_shards(emqx_ds:db()) -> [emqx_ds_replication_layer:shard_id()]. my_shards(DB) -> Site = this_site(), - eval_qlc( - qlc:q([ - Shard - || #?SHARD_TAB{shard = {D, Shard}, replica_set = ReplicaSet, in_sync_replicas = InSync} <- mnesia:table( - ?SHARD_TAB - ), - D =:= DB, - lists:member(Site, ReplicaSet) orelse lists:member(Site, InSync) - ]) + filter_shards(DB, fun(#?SHARD_TAB{replica_set = ReplicaSet, in_sync_replicas = InSync}) -> + lists:member(Site, ReplicaSet) orelse lists:member(Site, InSync) + end). + +-spec my_owned_shards(emqx_ds:db()) -> [emqx_ds_replication_layer:shard_id()]. +my_owned_shards(DB) -> + Self = node(), + filter_shards(DB, fun(#?SHARD_TAB{leader = Leader}) -> + Self =:= Leader + end). + +-spec leader_nodes(emqx_ds:db()) -> [node()]. +leader_nodes(DB) -> + lists:uniq( + filter_shards( + DB, + fun(#?SHARD_TAB{leader = Leader}) -> + Leader =/= undefined + end, + fun(#?SHARD_TAB{leader = Leader}) -> + Leader + end + ) ). -spec replica_set(emqx_ds:db(), emqx_ds_replication_layer:shard_id()) -> @@ -204,12 +225,25 @@ set_leader(DB, Shard, Node) -> {atomic, _} = mria:transaction(?SHARD, fun ?MODULE:set_leader_trans/3, [DB, Shard, Node]), ok. +-spec is_leader(node()) -> boolean(). +is_leader(Node) -> + {atomic, Result} = mria:transaction(?SHARD, fun ?MODULE:is_leader_trans/1, [Node]), + Result. + -spec open_db(emqx_ds:db(), emqx_ds_replication_layer:builtin_db_opts()) -> emqx_ds_replication_layer:builtin_db_opts(). open_db(DB, DefaultOpts) -> {atomic, Opts} = mria:transaction(?SHARD, fun ?MODULE:open_db_trans/2, [DB, DefaultOpts]), Opts. +-spec update_db_config(emqx_ds:db(), emqx_ds_replication_layer:builtin_db_opts()) -> + ok | {error, _}. +update_db_config(DB, DefaultOpts) -> + {atomic, Opts} = mria:transaction(?SHARD, fun ?MODULE:update_db_config_trans/2, [ + DB, DefaultOpts + ]), + Opts. + -spec drop_db(emqx_ds:db()) -> ok. drop_db(DB) -> _ = mria:transaction(?SHARD, fun ?MODULE:drop_db_trans/1, [DB]), @@ -226,6 +260,7 @@ init([]) -> logger:set_process_metadata(#{domain => [ds, meta]}), ensure_tables(), ensure_site(), + {ok, _} = mnesia:subscribe({table, ?META_TAB, detailed}), S = #s{}, {ok, S}. @@ -235,6 +270,18 @@ handle_call(_Call, _From, S) -> handle_cast(_Cast, S) -> {noreply, S}. +handle_info( + {mnesia_table_event, {write, ?META_TAB, #?META_TAB{db = DB, db_props = Options}, [_], _}}, S +) -> + MyShards = my_owned_shards(DB), + + lists:foreach( + fun(ShardId) -> + emqx_ds_storage_layer:update_config({DB, ShardId}, Options) + end, + MyShards + ), + {noreply, S}; handle_info(_Info, S) -> {noreply, S}. @@ -260,6 +307,31 @@ open_db_trans(DB, CreateOpts) -> Opts end. +-spec update_db_config_trans(emqx_ds:db(), emqx_ds_replication_layer:builtin_db_opts()) -> + ok | {error, database}. +update_db_config_trans(DB, CreateOpts) -> + case mnesia:wread({?META_TAB, DB}) of + [#?META_TAB{db_props = Opts}] -> + %% Since this is an update and not a reopen, + %% we should keep the shard number and replication factor + %% and not create a new shard server + #{ + n_shards := NShards, + replication_factor := ReplicationFactor + } = Opts, + + mnesia:write(#?META_TAB{ + db = DB, + db_props = CreateOpts#{ + n_shards := NShards, + replication_factor := ReplicationFactor + } + }), + ok; + [] -> + {error, no_database} + end. + -spec drop_db_trans(emqx_ds:db()) -> ok. drop_db_trans(DB) -> mnesia:delete({?META_TAB, DB}), @@ -287,6 +359,24 @@ set_leader_trans(DB, Shard, Node) -> Record = Record0#?SHARD_TAB{leader = Node}, mnesia:write(Record). +-spec is_leader_trans(node) -> boolean(). +is_leader_trans(Node) -> + case + mnesia:select( + ?SHARD_TAB, + ets:fun2ms(fun(#?SHARD_TAB{leader = Leader}) -> + Leader =:= Node + end), + 1, + read + ) + of + {[_ | _], _Cont} -> + true; + _ -> + false + end. + %%================================================================================ %% Internal functions %%================================================================================ @@ -346,7 +436,7 @@ create_shards(DB, NShards, ReplicationFactor) -> Hashes0 = [{hash(Shard, Site), Site} || Site <- AllSites], Hashes = lists:sort(Hashes0), {_, Sites} = lists:unzip(Hashes), - [First | _] = ReplicaSet = lists:sublist(Sites, 1, ReplicationFactor), + [First | ReplicaSet] = lists:sublist(Sites, 1, ReplicationFactor), Record = #?SHARD_TAB{ shard = {DB, Shard}, replica_set = ReplicaSet, @@ -369,3 +459,30 @@ eval_qlc(Q) -> {atomic, Result} = mria:ro_transaction(?SHARD, fun() -> qlc:eval(Q) end), Result end. + +filter_shards(DB) -> + filter_shards(DB, const(true)). + +-spec filter_shards(emqx_ds:db(), fun((_) -> boolean())) -> + [emqx_ds_replication_layer:shard_id()]. +filter_shards(DB, Predicte) -> + filter_shards(DB, Predicte, fun(#?SHARD_TAB{shard = {_, ShardId}}) -> + ShardId + end). + +filter_shards(DB, Predicate, Mapper) -> + eval_qlc( + qlc:q([ + Mapper(Shard) + || #?SHARD_TAB{shard = {D, _}} = Shard <- mnesia:table( + ?SHARD_TAB + ), + D =:= DB, + Predicate(Shard) + ]) + ). + +const(Result) -> + fun(_) -> + Result + end. diff --git a/apps/emqx_durable_storage/src/emqx_ds_storage_bitfield_lts.erl b/apps/emqx_durable_storage/src/emqx_ds_storage_bitfield_lts.erl index c2f533673..4c59a5f62 100644 --- a/apps/emqx_durable_storage/src/emqx_ds_storage_bitfield_lts.erl +++ b/apps/emqx_durable_storage/src/emqx_ds_storage_bitfield_lts.erl @@ -24,7 +24,15 @@ -export([]). %% behavior callbacks: --export([create/4, open/5, store_batch/4, get_streams/4, make_iterator/5, next/4]). +-export([ + create/4, + open/5, + store_batch/4, + get_streams/4, + make_iterator/5, + update_iterator/4, + next/4 +]). %% internal exports: -export([format_key/2]). @@ -236,6 +244,20 @@ make_iterator( ?last_seen_key => <<>> }}. +-spec update_iterator( + emqx_ds_storage_layer:shard_id(), + s(), + iterator(), + emqx_ds:message_key() +) -> {ok, iterator()}. +update_iterator( + _Shard, + _Data, + #{?tag := ?IT} = OldIter, + DSKey +) -> + {ok, OldIter#{?last_seen_key => DSKey}}. + next(_Shard, Schema = #s{ts_offset = TSOffset}, It, BatchSize) -> %% Compute safe cutoff time. %% It's the point in time where the last complete epoch ends, so we need to know @@ -329,7 +351,7 @@ traverse_interval(ITHandle, Filter, Cutoff, Key, Val, It0, Acc0, N) -> Msg = deserialize(Val), case check_message(Cutoff, It, Msg) of true -> - Acc = [Msg | Acc0], + Acc = [{Key, Msg} | Acc0], traverse_interval(ITHandle, Filter, Cutoff, It, Acc, N - 1); false -> traverse_interval(ITHandle, Filter, Cutoff, It, Acc0, N); diff --git a/apps/emqx_durable_storage/src/emqx_ds_storage_layer.erl b/apps/emqx_durable_storage/src/emqx_ds_storage_layer.erl index 99feea77a..ab64005b6 100644 --- a/apps/emqx_durable_storage/src/emqx_ds_storage_layer.erl +++ b/apps/emqx_durable_storage/src/emqx_ds_storage_layer.erl @@ -18,7 +18,17 @@ -behaviour(gen_server). %% Replication layer API: --export([open_shard/2, drop_shard/1, store_batch/3, get_streams/3, make_iterator/4, next/3]). +-export([ + open_shard/2, + drop_shard/1, + store_batch/3, + get_streams/3, + make_iterator/4, + update_iterator/3, + next/3, + update_config/2, + add_generation/1 +]). %% gen_server -export([start_link/2, init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2]). @@ -39,6 +49,8 @@ -include_lib("snabbkaffe/include/snabbkaffe.hrl"). +-define(REF(ShardId), {via, gproc, {n, l, {?MODULE, ShardId}}}). + %%================================================================================ %% Type declarations %%================================================================================ @@ -203,6 +215,27 @@ make_iterator( Err end. +-spec update_iterator( + shard_id(), iterator(), emqx_ds:message_key() +) -> + emqx_ds:make_iterator_result(iterator()). +update_iterator( + Shard, + #{?tag := ?IT, ?generation := GenId, ?enc := OldIter}, + DSKey +) -> + #{module := Mod, data := GenData} = generation_get(Shard, GenId), + case Mod:update_iterator(Shard, GenData, OldIter, DSKey) of + {ok, Iter} -> + {ok, #{ + ?tag => ?IT, + ?generation => GenId, + ?enc => Iter + }}; + {error, _} = Err -> + Err + end. + -spec next(shard_id(), iterator(), pos_integer()) -> emqx_ds:next_result(iterator()). next(Shard, Iter = #{?tag := ?IT, ?generation := GenId, ?enc := GenIter0}, BatchSize) -> @@ -220,13 +253,19 @@ next(Shard, Iter = #{?tag := ?IT, ?generation := GenId, ?enc := GenIter0}, Batch Error end. +-spec update_config(shard_id(), emqx_ds:create_db_opts()) -> ok. +update_config(ShardId, Options) -> + gen_server:call(?REF(ShardId), {?FUNCTION_NAME, Options}, infinity). + +-spec add_generation(shard_id()) -> ok. +add_generation(ShardId) -> + gen_server:call(?REF(ShardId), add_generation, infinity). + %%================================================================================ %% gen_server for the shard %%================================================================================ --define(REF(ShardId), {via, gproc, {n, l, {?MODULE, ShardId}}}). - --spec start_link(shard_id(), options()) -> +-spec start_link(shard_id(), emqx_ds:create_db_opts()) -> {ok, pid()}. start_link(Shard = {_, _}, Options) -> gen_server:start_link(?REF(Shard), ?MODULE, {Shard, Options}, []). @@ -271,6 +310,18 @@ init({ShardId, Options}) -> commit_metadata(S), {ok, S}. +handle_call({update_config, Options}, _From, #s{schema = Schema} = S0) -> + Prototype = maps:get(storage, Options), + S1 = S0#s{schema = Schema#{prototype := Prototype}}, + Since = emqx_message:timestamp_now(), + S = add_generation(S1, Since), + commit_metadata(S), + {reply, ok, S}; +handle_call(add_generation, _From, S0) -> + Since = emqx_message:timestamp_now(), + S = add_generation(S0, Since), + commit_metadata(S), + {reply, ok, S}; handle_call(#call_create_generation{since = Since}, _From, S0) -> S = add_generation(S0, Since), commit_metadata(S), @@ -313,11 +364,13 @@ open_shard(ShardId, DB, CFRefs, ShardSchema) -> -spec add_generation(server_state(), emqx_ds:time()) -> server_state(). add_generation(S0, Since) -> #s{shard_id = ShardId, db = DB, schema = Schema0, shard = Shard0, cf_refs = CFRefs0} = S0, - {GenId, Schema, NewCFRefs} = new_generation(ShardId, DB, Schema0, Since), + Schema1 = update_last_until(Schema0, Since), + Shard1 = update_last_until(Shard0, Since), + {GenId, Schema, NewCFRefs} = new_generation(ShardId, DB, Schema1, Since), CFRefs = NewCFRefs ++ CFRefs0, Key = {generation, GenId}, Generation = open_generation(ShardId, DB, CFRefs, GenId, maps:get(Key, Schema)), - Shard = Shard0#{Key => Generation}, + Shard = Shard1#{current_generation := GenId, Key => Generation}, S0#s{ cf_refs = CFRefs, schema = Schema, @@ -397,6 +450,13 @@ rocksdb_open(Shard, Options) -> db_dir({DB, ShardId}) -> filename:join([emqx:data_dir(), atom_to_list(DB), binary_to_list(ShardId)]). +-spec update_last_until(Schema, emqx_ds:time()) -> Schema when Schema :: shard_schema() | shard(). +update_last_until(Schema, Until) -> + #{current_generation := GenId} = Schema, + GenData0 = maps:get({generation, GenId}, Schema), + GenData = GenData0#{until := Until}, + Schema#{{generation, GenId} := GenData}. + %%-------------------------------------------------------------------------------- %% Schema access %%-------------------------------------------------------------------------------- diff --git a/apps/emqx_durable_storage/src/emqx_ds_storage_reference.erl b/apps/emqx_durable_storage/src/emqx_ds_storage_reference.erl index 6676faf88..da7ac79f6 100644 --- a/apps/emqx_durable_storage/src/emqx_ds_storage_reference.erl +++ b/apps/emqx_durable_storage/src/emqx_ds_storage_reference.erl @@ -27,7 +27,15 @@ -export([]). %% behavior callbacks: --export([create/4, open/5, store_batch/4, get_streams/4, make_iterator/5, next/4]). +-export([ + create/4, + open/5, + store_batch/4, + get_streams/4, + make_iterator/5, + update_iterator/4, + next/4 +]). %% internal exports: -export([]). @@ -97,6 +105,17 @@ make_iterator(_Shard, _Data, #stream{}, TopicFilter, StartTime) -> start_time = StartTime }}. +update_iterator(_Shard, _Data, OldIter, DSKey) -> + #it{ + topic_filter = TopicFilter, + start_time = StartTime + } = OldIter, + {ok, #it{ + topic_filter = TopicFilter, + start_time = StartTime, + last_seen_message_key = DSKey + }}. + next(_Shard, #s{db = DB, cf = CF}, It0, BatchSize) -> #it{topic_filter = TopicFilter, start_time = StartTime, last_seen_message_key = Key0} = It0, {ok, ITHandle} = rocksdb:iterator(DB, CF, []), @@ -125,7 +144,7 @@ do_next(TopicFilter, StartTime, IT, Action, NLeft, Key0, Acc) -> Msg = #message{topic = Topic, timestamp = TS} = binary_to_term(Blob), case emqx_topic:match(Topic, TopicFilter) andalso TS >= StartTime of true -> - do_next(TopicFilter, StartTime, IT, next, NLeft - 1, Key, [Msg | Acc]); + do_next(TopicFilter, StartTime, IT, next, NLeft - 1, Key, [{Key, Msg} | Acc]); false -> do_next(TopicFilter, StartTime, IT, next, NLeft, Key, Acc) end; diff --git a/apps/emqx_durable_storage/src/emqx_durable_storage.app.src b/apps/emqx_durable_storage/src/emqx_durable_storage.app.src index fd2c56293..f6f757cfd 100644 --- a/apps/emqx_durable_storage/src/emqx_durable_storage.app.src +++ b/apps/emqx_durable_storage/src/emqx_durable_storage.app.src @@ -2,7 +2,7 @@ {application, emqx_durable_storage, [ {description, "Message persistence and subscription replays for EMQX"}, % strict semver, bump manually! - {vsn, "0.1.9"}, + {vsn, "0.1.10"}, {modules, []}, {registered, []}, {applications, [kernel, stdlib, rocksdb, gproc, mria, emqx_utils]}, diff --git a/apps/emqx_durable_storage/src/proto/emqx_ds_proto_v1.erl b/apps/emqx_durable_storage/src/proto/emqx_ds_proto_v1.erl index 5104a417f..67ed1a3ca 100644 --- a/apps/emqx_durable_storage/src/proto/emqx_ds_proto_v1.erl +++ b/apps/emqx_durable_storage/src/proto/emqx_ds_proto_v1.erl @@ -19,7 +19,13 @@ -include_lib("emqx_utils/include/bpapi.hrl"). %% API: --export([drop_db/2, store_batch/5, get_streams/5, make_iterator/6, next/5]). +-export([ + drop_db/2, + store_batch/5, + get_streams/5, + make_iterator/6, + next/5 +]). %% behavior callbacks: -export([introduced_in/0]). @@ -64,7 +70,7 @@ make_iterator(Node, DB, Shard, Stream, TopicFilter, StartTime) -> emqx_ds_storage_layer:iterator(), pos_integer() ) -> - {ok, emqx_ds_storage_layer:iterator(), [emqx_types:message()]} + {ok, emqx_ds_storage_layer:iterator(), [{emqx_ds:message_key(), [emqx_types:message()]}]} | {ok, end_of_stream} | {error, _}. next(Node, DB, Shard, Iter, BatchSize) -> diff --git a/apps/emqx_durable_storage/src/proto/emqx_ds_proto_v2.erl b/apps/emqx_durable_storage/src/proto/emqx_ds_proto_v2.erl new file mode 100644 index 000000000..f771f1a8b --- /dev/null +++ b/apps/emqx_durable_storage/src/proto/emqx_ds_proto_v2.erl @@ -0,0 +1,124 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2023 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. +%%-------------------------------------------------------------------- +-module(emqx_ds_proto_v2). + +-behavior(emqx_bpapi). + +-include_lib("emqx_utils/include/bpapi.hrl"). +%% API: +-export([ + drop_db/2, + store_batch/5, + get_streams/5, + make_iterator/6, + next/5, + + %% introduced in v2 + update_iterator/5, + add_generation/2 +]). + +%% behavior callbacks: +-export([introduced_in/0]). + +%%================================================================================ +%% API funcions +%%================================================================================ + +-spec drop_db([node()], emqx_ds:db()) -> + [{ok, ok} | {error, _}]. +drop_db(Node, DB) -> + erpc:multicall(Node, emqx_ds_replication_layer, do_drop_db_v1, [DB]). + +-spec get_streams( + node(), + emqx_ds:db(), + emqx_ds_replication_layer:shard_id(), + emqx_ds:topic_filter(), + emqx_ds:time() +) -> + [{integer(), emqx_ds_storage_layer:stream()}]. +get_streams(Node, DB, Shard, TopicFilter, Time) -> + erpc:call(Node, emqx_ds_replication_layer, do_get_streams_v1, [DB, Shard, TopicFilter, Time]). + +-spec make_iterator( + node(), + emqx_ds:db(), + emqx_ds_replication_layer:shard_id(), + emqx_ds_storage_layer:stream(), + emqx_ds:topic_filter(), + emqx_ds:time() +) -> + {ok, emqx_ds_storage_layer:iterator()} | {error, _}. +make_iterator(Node, DB, Shard, Stream, TopicFilter, StartTime) -> + erpc:call(Node, emqx_ds_replication_layer, do_make_iterator_v1, [ + DB, Shard, Stream, TopicFilter, StartTime + ]). + +-spec next( + node(), + emqx_ds:db(), + emqx_ds_replication_layer:shard_id(), + emqx_ds_storage_layer:iterator(), + pos_integer() +) -> + {ok, emqx_ds_storage_layer:iterator(), [{emqx_ds:message_key(), [emqx_types:message()]}]} + | {ok, end_of_stream} + | {error, _}. +next(Node, DB, Shard, Iter, BatchSize) -> + emqx_rpc:call(Shard, Node, emqx_ds_replication_layer, do_next_v1, [DB, Shard, Iter, BatchSize]). + +-spec store_batch( + node(), + emqx_ds:db(), + emqx_ds_replication_layer:shard_id(), + emqx_ds_replication_layer:batch(), + emqx_ds:message_store_opts() +) -> + emqx_ds:store_batch_result(). +store_batch(Node, DB, Shard, Batch, Options) -> + emqx_rpc:call(Shard, Node, emqx_ds_replication_layer, do_store_batch_v1, [ + DB, Shard, Batch, Options + ]). + +%%-------------------------------------------------------------------------------- +%% Introduced in V2 +%%-------------------------------------------------------------------------------- + +-spec update_iterator( + node(), + emqx_ds:db(), + emqx_ds_replication_layer:shard_id(), + emqx_ds_storage_layer:iterator(), + emqx_ds:message_key() +) -> + {ok, emqx_ds_storage_layer:iterator()} | {error, _}. +update_iterator(Node, DB, Shard, OldIter, DSKey) -> + erpc:call(Node, emqx_ds_replication_layer, do_update_iterator_v2, [ + DB, Shard, OldIter, DSKey + ]). + +-spec add_generation([node()], emqx_ds:db()) -> + [{ok, ok} | {error, _}]. +add_generation(Node, DB) -> + erpc:multicall(Node, emqx_ds_replication_layer, do_add_generation_v2, [DB]). + +%%================================================================================ +%% behavior callbacks +%%================================================================================ + +introduced_in() -> + "5.5.0". diff --git a/apps/emqx_durable_storage/test/emqx_ds_SUITE.erl b/apps/emqx_durable_storage/test/emqx_ds_SUITE.erl index 8a46804b0..e6984f200 100644 --- a/apps/emqx_durable_storage/test/emqx_ds_SUITE.erl +++ b/apps/emqx_durable_storage/test/emqx_ds_SUITE.erl @@ -50,7 +50,7 @@ t_00_smoke_open_drop(_Config) -> lists:foreach( fun(Shard) -> ?assertEqual( - {ok, [Site]}, emqx_ds_replication_layer_meta:replica_set(DB, Shard) + {ok, []}, emqx_ds_replication_layer_meta:replica_set(DB, Shard) ), ?assertEqual( [Site], emqx_ds_replication_layer_meta:in_sync_replicas(DB, Shard) @@ -101,7 +101,7 @@ t_03_smoke_iterate(_Config) -> [{_, Stream}] = emqx_ds:get_streams(DB, TopicFilter, StartTime), {ok, Iter0} = emqx_ds:make_iterator(DB, Stream, TopicFilter, StartTime), {ok, Iter, Batch} = iterate(DB, Iter0, 1), - ?assertEqual(Msgs, Batch, {Iter0, Iter}). + ?assertEqual(Msgs, [Msg || {_Key, Msg} <- Batch], {Iter0, Iter}). %% Verify that iterators survive restart of the application. This is %% an important property, since the lifetime of the iterators is tied @@ -128,7 +128,154 @@ t_04_restart(_Config) -> ok = emqx_ds:open_db(DB, opts()), %% The old iterator should be still operational: {ok, Iter, Batch} = iterate(DB, Iter0, 1), - ?assertEqual(Msgs, Batch, {Iter0, Iter}). + ?assertEqual(Msgs, [Msg || {_Key, Msg} <- Batch], {Iter0, Iter}). + +%% Check that we can create iterators directly from DS keys. +t_05_update_iterator(_Config) -> + DB = ?FUNCTION_NAME, + ?assertMatch(ok, emqx_ds:open_db(DB, opts())), + TopicFilter = ['#'], + StartTime = 0, + Msgs = [ + message(<<"foo/bar">>, <<"1">>, 0), + message(<<"foo">>, <<"2">>, 1), + message(<<"bar/bar">>, <<"3">>, 2) + ], + ?assertMatch(ok, emqx_ds:store_batch(DB, Msgs)), + [{_, Stream}] = emqx_ds:get_streams(DB, TopicFilter, StartTime), + {ok, Iter0} = emqx_ds:make_iterator(DB, Stream, TopicFilter, StartTime), + Res0 = emqx_ds:next(DB, Iter0, 1), + ?assertMatch({ok, _OldIter, [{_Key0, _Msg0}]}, Res0), + {ok, OldIter, [{Key0, Msg0}]} = Res0, + Res1 = emqx_ds:update_iterator(DB, OldIter, Key0), + ?assertMatch({ok, _Iter1}, Res1), + {ok, Iter1} = Res1, + {ok, FinalIter, Batch} = iterate(DB, Iter1, 1), + AllMsgs = [Msg0 | [Msg || {_Key, Msg} <- Batch]], + ?assertEqual(Msgs, AllMsgs, #{from_key => Iter1, final_iter => FinalIter}), + ok. + +t_05_update_config(_Config) -> + DB = ?FUNCTION_NAME, + ?assertMatch(ok, emqx_ds:open_db(DB, opts())), + TopicFilter = ['#'], + + DataSet = update_data_set(), + + ToMsgs = fun(Datas) -> + lists:map( + fun({Topic, Payload}) -> + message(Topic, Payload, emqx_message:timestamp_now()) + end, + Datas + ) + end, + + {_, StartTimes, MsgsList} = + lists:foldl( + fun + (Datas, {true, TimeAcc, MsgAcc}) -> + Msgs = ToMsgs(Datas), + ?assertMatch(ok, emqx_ds:store_batch(DB, Msgs)), + {false, TimeAcc, [Msgs | MsgAcc]}; + (Datas, {Any, TimeAcc, MsgAcc}) -> + timer:sleep(500), + ?assertMatch(ok, emqx_ds:add_generation(DB, opts())), + timer:sleep(500), + StartTime = emqx_message:timestamp_now(), + Msgs = ToMsgs(Datas), + ?assertMatch(ok, emqx_ds:store_batch(DB, Msgs)), + {Any, [StartTime | TimeAcc], [Msgs | MsgAcc]} + end, + {true, [emqx_message:timestamp_now()], []}, + DataSet + ), + + Checker = fun({StartTime, Msgs0}, Acc) -> + Msgs = Msgs0 ++ Acc, + Batch = fetch_all(DB, TopicFilter, StartTime), + ?assertEqual(Msgs, Batch, {StartTime}), + Msgs + end, + lists:foldl(Checker, [], lists:zip(StartTimes, MsgsList)). + +t_06_add_generation(_Config) -> + DB = ?FUNCTION_NAME, + ?assertMatch(ok, emqx_ds:open_db(DB, opts())), + TopicFilter = ['#'], + + DataSet = update_data_set(), + + ToMsgs = fun(Datas) -> + lists:map( + fun({Topic, Payload}) -> + message(Topic, Payload, emqx_message:timestamp_now()) + end, + Datas + ) + end, + + {_, StartTimes, MsgsList} = + lists:foldl( + fun + (Datas, {true, TimeAcc, MsgAcc}) -> + Msgs = ToMsgs(Datas), + ?assertMatch(ok, emqx_ds:store_batch(DB, Msgs)), + {false, TimeAcc, [Msgs | MsgAcc]}; + (Datas, {Any, TimeAcc, MsgAcc}) -> + timer:sleep(500), + ?assertMatch(ok, emqx_ds:add_generation(DB)), + timer:sleep(500), + StartTime = emqx_message:timestamp_now(), + Msgs = ToMsgs(Datas), + ?assertMatch(ok, emqx_ds:store_batch(DB, Msgs)), + {Any, [StartTime | TimeAcc], [Msgs | MsgAcc]} + end, + {true, [emqx_message:timestamp_now()], []}, + DataSet + ), + + Checker = fun({StartTime, Msgs0}, Acc) -> + Msgs = Msgs0 ++ Acc, + Batch = fetch_all(DB, TopicFilter, StartTime), + ?assertEqual(Msgs, Batch, {StartTime}), + Msgs + end, + lists:foldl(Checker, [], lists:zip(StartTimes, MsgsList)). + +update_data_set() -> + [ + [ + {<<"foo/bar">>, <<"1">>} + ], + + [ + {<<"foo">>, <<"2">>} + ], + + [ + {<<"bar/bar">>, <<"3">>} + ] + ]. + +fetch_all(DB, TopicFilter, StartTime) -> + Streams0 = emqx_ds:get_streams(DB, TopicFilter, StartTime), + Streams = lists:sort( + fun({{_, A}, _}, {{_, B}, _}) -> + A < B + end, + Streams0 + ), + lists:foldl( + fun({_, Stream}, Acc) -> + {ok, Iter0} = emqx_ds:make_iterator(DB, Stream, TopicFilter, StartTime), + {ok, _, Msgs0} = iterate(DB, Iter0, StartTime), + Msgs = lists:map(fun({_, Msg}) -> Msg end, Msgs0), + Acc ++ Msgs + end, + [], + Streams + ). message(Topic, Payload, PublishedAt) -> #message{ @@ -147,6 +294,8 @@ iterate(DB, It0, BatchSize, Acc) -> {ok, It, Acc}; {ok, It, Msgs} -> iterate(DB, It, BatchSize, Acc ++ Msgs); + {ok, end_of_stream} -> + {ok, It0, Acc}; Ret -> Ret end. diff --git a/apps/emqx_durable_storage/test/emqx_ds_storage_bitfield_lts_SUITE.erl b/apps/emqx_durable_storage/test/emqx_ds_storage_bitfield_lts_SUITE.erl index 7b733406d..fc6049669 100644 --- a/apps/emqx_durable_storage/test/emqx_ds_storage_bitfield_lts_SUITE.erl +++ b/apps/emqx_durable_storage/test/emqx_ds_storage_bitfield_lts_SUITE.erl @@ -64,7 +64,8 @@ t_iterate(_Config) -> begin [{_Rank, Stream}] = emqx_ds_storage_layer:get_streams(?SHARD, parse_topic(Topic), 0), {ok, It} = emqx_ds_storage_layer:make_iterator(?SHARD, Stream, parse_topic(Topic), 0), - {ok, NextIt, Messages} = emqx_ds_storage_layer:next(?SHARD, It, 100), + {ok, NextIt, MessagesAndKeys} = emqx_ds_storage_layer:next(?SHARD, It, 100), + Messages = [Msg || {_DSKey, Msg} <- MessagesAndKeys], ?assertEqual( lists:map(fun integer_to_binary/1, Timestamps), payloads(Messages) @@ -249,7 +250,7 @@ dump_stream(Shard, Stream, TopicFilter, StartTime) -> {ok, _NextIt, []} -> []; {ok, NextIt, Batch} -> - Batch ++ F(NextIt, N - 1) + [Msg || {_DSKey, Msg} <- Batch] ++ F(NextIt, N - 1) end end, MaxIterations = 1000000, diff --git a/apps/emqx_ft/test/emqx_ft_storage_fs_reader_SUITE.erl b/apps/emqx_ft/test/emqx_ft_storage_fs_reader_SUITE.erl index f0b658e0d..6d8d13986 100644 --- a/apps/emqx_ft/test/emqx_ft_storage_fs_reader_SUITE.erl +++ b/apps/emqx_ft/test/emqx_ft_storage_fs_reader_SUITE.erl @@ -125,6 +125,7 @@ t_bad_messages(Config) -> ). t_nonexistent_file(_Config) -> + erlang:process_flag(trap_exit, true), ?assertEqual( {error, enoent}, emqx_ft_storage_fs_reader:start_link(self(), "/a/b/c/bar") diff --git a/apps/emqx_gateway/src/emqx_gateway.app.src b/apps/emqx_gateway/src/emqx_gateway.app.src index f87b9a5bf..143468275 100644 --- a/apps/emqx_gateway/src/emqx_gateway.app.src +++ b/apps/emqx_gateway/src/emqx_gateway.app.src @@ -1,7 +1,7 @@ %% -*- mode: erlang -*- {application, emqx_gateway, [ {description, "The Gateway management application"}, - {vsn, "0.1.29"}, + {vsn, "0.1.30"}, {registered, []}, {mod, {emqx_gateway_app, []}}, {applications, [kernel, stdlib, emqx, emqx_auth, emqx_ctl]}, diff --git a/apps/emqx_gateway/src/emqx_gateway_conf.erl b/apps/emqx_gateway/src/emqx_gateway_conf.erl index 30c386f44..accd09a23 100644 --- a/apps/emqx_gateway/src/emqx_gateway_conf.erl +++ b/apps/emqx_gateway/src/emqx_gateway_conf.erl @@ -132,7 +132,7 @@ maps_key_take([K | Ks], M, Acc) -> validate_listener_name(Name) -> try - {match, _} = re:run(Name, "^[0-9a-zA-Z_-]+$"), + {match, _} = re:run(Name, "^[a-zA-Z][0-9a-zA-Z_-]*$"), ok catch _:_ -> @@ -140,7 +140,7 @@ validate_listener_name(Name) -> {badconf, #{ key => name, value => Name, - reason => illegal_listener_name + reason => bad_listener_name }} ) end. diff --git a/apps/emqx_gateway_exproto/src/emqx_gateway_exproto.app.src b/apps/emqx_gateway_exproto/src/emqx_gateway_exproto.app.src index 2eab2cf2f..63620c930 100644 --- a/apps/emqx_gateway_exproto/src/emqx_gateway_exproto.app.src +++ b/apps/emqx_gateway_exproto/src/emqx_gateway_exproto.app.src @@ -1,7 +1,7 @@ %% -*- mode: erlang -*- {application, emqx_gateway_exproto, [ {description, "ExProto Gateway"}, - {vsn, "0.1.7"}, + {vsn, "0.1.8"}, {registered, []}, {applications, [kernel, stdlib, grpc, emqx, emqx_gateway]}, {env, []}, diff --git a/apps/emqx_gateway_exproto/src/emqx_gateway_exproto.erl b/apps/emqx_gateway_exproto/src/emqx_gateway_exproto.erl index ec2540ec2..17180cdb6 100644 --- a/apps/emqx_gateway_exproto/src/emqx_gateway_exproto.erl +++ b/apps/emqx_gateway_exproto/src/emqx_gateway_exproto.erl @@ -143,11 +143,11 @@ start_grpc_server(GwName, Options = #{bind := ListenOn}) -> false -> []; true -> + Opts1 = maps:get(ssl, Options, #{}), + Opts2 = maps:without([handshake_timeout], Opts1), + SSLOpts = emqx_tls_lib:to_server_opts(tls, Opts2), [ - {ssl_options, - maps:to_list( - maps:without([enable, handshake_timeout], maps:get(ssl, Options, #{})) - )} + {ssl_options, SSLOpts} ] end, ListenOnStr = emqx_listeners:format_bind(ListenOn), @@ -166,7 +166,7 @@ start_grpc_server(GwName, Options = #{bind := ListenOn}) -> {badconf, #{ key => server, value => Options, - reason => illegal_grpc_server_confs + reason => invalid_grpc_server_confs }} ) end; @@ -175,7 +175,7 @@ start_grpc_server(_GwName, Options) -> {badconf, #{ key => server, value => Options, - reason => illegal_grpc_server_confs + reason => invalid_grpc_server_confs }} ). @@ -196,24 +196,24 @@ start_grpc_client_channel( {badconf, #{ key => address, value => Address, - reason => illegal_grpc_address + reason => invalid_grpc_address }} ) end, - case emqx_utils_maps:deep_get([ssl_options, enable], Options, false) of + SSLOpts = emqx_utils_maps:deep_get([ssl_options], Options, #{}), + case maps:get(enable, SSLOpts, false) of false -> SvrAddr = compose_http_uri(http, Host, Port), grpc_client_sup:create_channel_pool(GwName, SvrAddr, #{}); true -> - SslOpts = maps:to_list(maps:get(ssl, Options, #{})), + SSLOpts1 = [{nodelay, true} | emqx_tls_lib:to_client_opts(SSLOpts)], ClientOpts = #{ gun_opts => #{ transport => ssl, - transport_opts => SslOpts + transport_opts => SSLOpts1 } }, - SvrAddr = compose_http_uri(https, Host, Port), grpc_client_sup:create_channel_pool(GwName, SvrAddr, ClientOpts) end; @@ -222,7 +222,7 @@ start_grpc_client_channel(_GwName, Options) -> {badconf, #{ key => handler, value => Options, - reason => ililegal_grpc_client_confs + reason => invalid_grpc_client_confs }} ). diff --git a/apps/emqx_gateway_exproto/test/emqx_exproto_SUITE.erl b/apps/emqx_gateway_exproto/test/emqx_exproto_SUITE.erl index 2d2583beb..b6d2a6257 100644 --- a/apps/emqx_gateway_exproto/test/emqx_exproto_SUITE.erl +++ b/apps/emqx_gateway_exproto/test/emqx_exproto_SUITE.erl @@ -586,11 +586,11 @@ open(udp) -> {ok, Sock} = gen_udp:open(0, ?TCPOPTS), {udp, Sock}; open(ssl) -> - SslOpts = maps:to_list(client_ssl_opts()), + SslOpts = client_ssl_opts(), {ok, SslSock} = ssl:connect("127.0.0.1", 7993, ?TCPOPTS ++ SslOpts), {ssl, SslSock}; open(dtls) -> - SslOpts = maps:to_list(client_ssl_opts()), + SslOpts = client_ssl_opts(), {ok, SslSock} = ssl:connect("127.0.0.1", 7993, ?DTLSOPTS ++ SslOpts), {dtls, SslSock}. @@ -691,7 +691,8 @@ dtls_opts() -> %% Client-Opts client_ssl_opts() -> - certs("client-key.pem", "client-cert.pem", "cacert.pem"). + OptsWithCerts = certs("client-key.pem", "client-cert.pem", "cacert.pem"), + [{verify, verify_none} | maps:to_list(OptsWithCerts)]. certs(Key, Cert, CACert) -> CertsPath = emqx_common_test_helpers:deps_path(emqx, "etc/certs"), diff --git a/apps/emqx_gateway_ocpp/src/emqx_gateway_ocpp.app.src b/apps/emqx_gateway_ocpp/src/emqx_gateway_ocpp.app.src index 2aa6042ba..e882d7710 100644 --- a/apps/emqx_gateway_ocpp/src/emqx_gateway_ocpp.app.src +++ b/apps/emqx_gateway_ocpp/src/emqx_gateway_ocpp.app.src @@ -1,6 +1,6 @@ {application, emqx_gateway_ocpp, [ {description, "OCPP-J 1.6 Gateway for EMQX"}, - {vsn, "0.1.1"}, + {vsn, "0.1.2"}, {registered, []}, {applications, [kernel, stdlib, jesse, emqx, emqx_gateway]}, {env, []}, diff --git a/apps/emqx_gateway_ocpp/src/emqx_ocpp_connection.erl b/apps/emqx_gateway_ocpp/src/emqx_ocpp_connection.erl index 6eadb169c..3147324f7 100644 --- a/apps/emqx_gateway_ocpp/src/emqx_ocpp_connection.erl +++ b/apps/emqx_gateway_ocpp/src/emqx_ocpp_connection.erl @@ -250,7 +250,7 @@ init_state_and_channel([Req, Opts, _WsOpts], _State = undefined) -> cowboy_req:parse_cookies(Req) catch error:badarg -> - ?SLOG(error, #{msg => "illegal_cookie"}), + ?SLOG(error, #{msg => "bad_cookie"}), undefined; Error:Reason -> ?SLOG(error, #{ diff --git a/apps/emqx_management/src/emqx_mgmt_api_clients.erl b/apps/emqx_management/src/emqx_mgmt_api_clients.erl index a0436298e..dee4a235c 100644 --- a/apps/emqx_management/src/emqx_mgmt_api_clients.erl +++ b/apps/emqx_management/src/emqx_mgmt_api_clients.erl @@ -113,7 +113,7 @@ schema("/clients") -> in => query, required => false, desc => <<"Node name">>, - example => atom_to_list(node()) + example => <<"emqx@127.0.0.1">> })}, {username, hoconsc:mk(binary(), #{ @@ -196,10 +196,16 @@ schema("/clients") -> })} ], responses => #{ - 200 => [ - {data, hoconsc:mk(hoconsc:array(hoconsc:ref(?MODULE, client)), #{})}, - {meta, hoconsc:mk(hoconsc:ref(emqx_dashboard_swagger, meta), #{})} - ], + 200 => + emqx_dashboard_swagger:schema_with_example(?R_REF(clients), #{ + <<"data">> => [client_example()], + <<"meta">> => #{ + <<"count">> => 1, + <<"limit">> => 50, + <<"page">> => 1, + <<"hasnext">> => false + } + }), 400 => emqx_dashboard_swagger:error_codes( ['INVALID_PARAMETER'], <<"Invalid parameters">> @@ -230,7 +236,10 @@ schema("/clients/:clientid") -> tags => ?TAGS, parameters => [{clientid, hoconsc:mk(binary(), #{in => path})}], responses => #{ - 200 => hoconsc:mk(hoconsc:ref(?MODULE, client), #{}), + 200 => emqx_dashboard_swagger:schema_with_example( + ?R_REF(client), + client_example() + ), 404 => emqx_dashboard_swagger:error_codes( ['CLIENTID_NOT_FOUND'], <<"Client ID not found">> ) @@ -367,7 +376,10 @@ schema("/clients/:clientid/keepalive") -> parameters => [{clientid, hoconsc:mk(binary(), #{in => path})}], 'requestBody' => hoconsc:mk(hoconsc:ref(?MODULE, keepalive)), responses => #{ - 200 => hoconsc:mk(hoconsc:ref(?MODULE, client), #{}), + 200 => emqx_dashboard_swagger:schema_with_example( + ?R_REF(client), + client_example() + ), 404 => emqx_dashboard_swagger:error_codes( ['CLIENTID_NOT_FOUND'], <<"Client ID not found">> ) @@ -375,6 +387,11 @@ schema("/clients/:clientid/keepalive") -> } }. +fields(clients) -> + [ + {data, hoconsc:mk(hoconsc:array(?REF(client)), #{})}, + {meta, hoconsc:mk(hoconsc:ref(emqx_dashboard_swagger, meta), #{})} + ]; fields(client) -> [ {awaiting_rel_cnt, @@ -978,3 +995,58 @@ format_authz_cache({{PubSub, Topic}, {AuthzResult, Timestamp}}) -> to_topic_info(Data) -> M = maps:with([<<"topic">>, <<"qos">>, <<"nl">>, <<"rap">>, <<"rh">>], Data), emqx_utils_maps:safe_atom_key_map(M). + +client_example() -> + #{ + <<"recv_oct">> => 49, + <<"expiry_interval">> => 0, + <<"created_at">> => <<"2024-01-01T12:34:56.789+08:00">>, + <<"awaiting_rel_max">> => 100, + <<"send_msg">> => 0, + <<"enable_authn">> => true, + <<"send_msg.qos2">> => 0, + <<"peerport">> => 52571, + <<"connected_at">> => <<"2024-01-01T12:34:56.789+08:00">>, + <<"send_msg.dropped.too_large">> => 0, + <<"inflight_cnt">> => 0, + <<"keepalive">> => 60, + <<"node">> => <<"emqx@127.0.0.1">>, + <<"send_cnt">> => 4, + <<"recv_msg.dropped.await_pubrel_timeout">> => 0, + <<"recv_msg.dropped">> => 0, + <<"inflight_max">> => 32, + <<"proto_name">> => <<"MQTT">>, + <<"send_msg.dropped.expired">> => 0, + <<"awaiting_rel_cnt">> => 0, + <<"mqueue_max">> => 1000, + <<"send_oct">> => 31, + <<"send_msg.dropped.queue_full">> => 0, + <<"mqueue_len">> => 0, + <<"heap_size">> => 610, + <<"is_persistent">> => false, + <<"send_msg.qos0">> => 0, + <<"clean_start">> => true, + <<"mountpoint">> => <<"null">>, + <<"proto_ver">> => 5, + <<"ip_address">> => <<"127.0.0.1">>, + <<"mqueue_dropped">> => 0, + <<"port">> => 52571, + <<"listener">> => <<"tcp:default">>, + <<"recv_msg.qos2">> => 0, + <<"recv_msg.qos1">> => 0, + <<"is_bridge">> => false, + <<"subscriptions_cnt">> => 1, + <<"username">> => null, + <<"send_msg.dropped">> => 0, + <<"send_pkt">> => 4, + <<"subscriptions_max">> => <<"infinity">>, + <<"send_msg.qos1">> => 0, + <<"connected">> => true, + <<"reductions">> => 6836, + <<"mailbox_len">> => 0, + <<"clientid">> => "01", + <<"recv_msg">> => 0, + <<"recv_pkt">> => 4, + <<"recv_cnt">> => 4, + <<"recv_msg.qos0">> => 0 + }. diff --git a/apps/emqx_management/src/emqx_mgmt_util.erl b/apps/emqx_management/src/emqx_mgmt_util.erl index b81b39b07..c266dce1b 100644 --- a/apps/emqx_management/src/emqx_mgmt_util.erl +++ b/apps/emqx_management/src/emqx_mgmt_util.erl @@ -61,10 +61,8 @@ kmg(Byte) -> kmg(F, S) -> iolist_to_binary(io_lib:format("~.2f~ts", [F, S])). -ntoa({0, 0, 0, 0, 0, 16#ffff, AB, CD}) -> - inet_parse:ntoa({AB bsr 8, AB rem 256, CD bsr 8, CD rem 256}); -ntoa(IP) -> - inet_parse:ntoa(IP). +ntoa(Ip) -> + emqx_utils:ntoa(Ip). merge_maps(Default, New) -> maps:fold( diff --git a/apps/emqx_opentelemetry/src/emqx_opentelemetry.app.src b/apps/emqx_opentelemetry/src/emqx_opentelemetry.app.src index 95249ff85..4cde26326 100644 --- a/apps/emqx_opentelemetry/src/emqx_opentelemetry.app.src +++ b/apps/emqx_opentelemetry/src/emqx_opentelemetry.app.src @@ -1,6 +1,6 @@ {application, emqx_opentelemetry, [ {description, "OpenTelemetry for EMQX Broker"}, - {vsn, "0.2.1"}, + {vsn, "0.2.2"}, {registered, []}, {mod, {emqx_otel_app, []}}, {applications, [ diff --git a/apps/emqx_opentelemetry/src/emqx_otel_config.erl b/apps/emqx_opentelemetry/src/emqx_otel_config.erl index 4a6b09dd6..590a8a2a8 100644 --- a/apps/emqx_opentelemetry/src/emqx_otel_config.erl +++ b/apps/emqx_opentelemetry/src/emqx_otel_config.erl @@ -183,12 +183,13 @@ tr_handler_conf(#{logs := LogsConf, exporter := ExporterConf}) -> ssl_opts(Endpoint, SSLOpts) -> case is_ssl(Endpoint) of true -> - emqx_tls_lib:to_client_opts(SSLOpts); + %% force enable ssl + emqx_tls_lib:to_client_opts(SSLOpts#{enable => true}); false -> [] end. -is_ssl(<<"https://", _/binary>> = _Endpoint) -> +is_ssl(<<"https://", _/binary>>) -> true; -is_ssl(_Endpoint) -> +is_ssl(<<"http://", _/binary>>) -> false. diff --git a/apps/emqx_postgresql/rebar.config b/apps/emqx_postgresql/rebar.config index 1ae1309c9..a4b84ef0f 100644 --- a/apps/emqx_postgresql/rebar.config +++ b/apps/emqx_postgresql/rebar.config @@ -2,7 +2,7 @@ {erl_opts, [debug_info]}. {deps, [ - {epgsql, {git, "https://github.com/emqx/epgsql", {tag, "4.7.0.1"}}}, + {epgsql, {git, "https://github.com/emqx/epgsql", {tag, "4.7.1.1"}}}, {emqx_connector, {path, "../../apps/emqx_connector"}}, {emqx_resource, {path, "../../apps/emqx_resource"}} ]}. diff --git a/apps/emqx_rule_engine/src/emqx_rule_engine.app.src b/apps/emqx_rule_engine/src/emqx_rule_engine.app.src index 6b858d17b..a0b8e8ca2 100644 --- a/apps/emqx_rule_engine/src/emqx_rule_engine.app.src +++ b/apps/emqx_rule_engine/src/emqx_rule_engine.app.src @@ -2,7 +2,7 @@ {application, emqx_rule_engine, [ {description, "EMQX Rule Engine"}, % strict semver, bump manually! - {vsn, "5.0.31"}, + {vsn, "5.0.32"}, {modules, []}, {registered, [emqx_rule_engine_sup, emqx_rule_engine]}, {applications, [ diff --git a/apps/emqx_rule_engine/src/emqx_rule_events.erl b/apps/emqx_rule_engine/src/emqx_rule_events.erl index ac9e077eb..367afc654 100644 --- a/apps/emqx_rule_engine/src/emqx_rule_events.erl +++ b/apps/emqx_rule_engine/src/emqx_rule_events.erl @@ -1039,9 +1039,10 @@ reason({shutdown, Reason}) when is_atom(Reason) -> Reason; reason({Error, _}) when is_atom(Error) -> Error; reason(_) -> internal_error. -ntoa(undefined) -> undefined; -ntoa({IpAddr, Port}) -> iolist_to_binary([inet:ntoa(IpAddr), ":", integer_to_list(Port)]); -ntoa(IpAddr) -> iolist_to_binary(inet:ntoa(IpAddr)). +ntoa(undefined) -> + undefined; +ntoa(IpOrIpPort) -> + iolist_to_binary(emqx_utils:ntoa(IpOrIpPort)). event_name(?BRIDGE_HOOKPOINT(_) = Bridge) -> Bridge; event_name(<<"$events/client_connected">>) -> 'client.connected'; diff --git a/apps/emqx_s3/rebar.config b/apps/emqx_s3/rebar.config index 1d64e6677..e34406e54 100644 --- a/apps/emqx_s3/rebar.config +++ b/apps/emqx_s3/rebar.config @@ -1,6 +1,6 @@ {deps, [ {emqx, {path, "../../apps/emqx"}}, - {erlcloud, {git, "https://github.com/emqx/erlcloud", {tag, "3.7.0-emqx-2"}}}, + {erlcloud, {git, "https://github.com/emqx/erlcloud", {tag, "3.7.0.3"}}}, {emqx_bridge_http, {path, "../emqx_bridge_http"}} ]}. diff --git a/apps/emqx_s3/test/emqx_s3_client_SUITE.erl b/apps/emqx_s3/test/emqx_s3_client_SUITE.erl index 434510867..d3901cd05 100644 --- a/apps/emqx_s3/test/emqx_s3_client_SUITE.erl +++ b/apps/emqx_s3/test/emqx_s3_client_SUITE.erl @@ -129,7 +129,7 @@ t_url(Config) -> ?assertMatch( {ok, {{_StatusLine, 200, "OK"}, _Headers, "data"}}, - httpc:request(Url) + httpc:request(get, {Url, []}, [{ssl, [{verify, verify_none}]}], []) ). t_no_acl(Config) -> diff --git a/apps/emqx_s3/test/emqx_s3_uploader_SUITE.erl b/apps/emqx_s3/test/emqx_s3_uploader_SUITE.erl index 6ba0e3ed9..90a32d948 100644 --- a/apps/emqx_s3/test/emqx_s3_uploader_SUITE.erl +++ b/apps/emqx_s3/test/emqx_s3_uploader_SUITE.erl @@ -64,13 +64,13 @@ groups() -> {tcp_cases, [ t_config_switch, - t_config_switch_http_settings, t_too_large, t_no_profile ]}, {tls_cases, [ - t_tls_error + t_tls_error, + t_config_switch_http_settings ]}, {noconn_errors, [{group, transport_errors}]}, @@ -205,7 +205,8 @@ t_signed_url_download(_Config) -> emqx_s3_client:uri(Client, Key) end), - {ok, {_, _, Body}} = httpc:request(get, {SignedUrl, []}, [], []), + HttpOpts = [{ssl, [{verify, verify_none}]}], + {ok, {_, _, Body}} = httpc:request(get, {SignedUrl, []}, HttpOpts, []), ?assertEqual( iolist_to_binary(Data), @@ -222,7 +223,8 @@ t_signed_nonascii_url_download(_Config) -> emqx_s3_client:uri(Client, Key) end), - {ok, {_, _, Body}} = httpc:request(get, {SignedUrl, []}, [], []), + HttpOpts = [{ssl, [{verify, verify_none}]}], + {ok, {_, _, Body}} = httpc:request(get, {SignedUrl, []}, HttpOpts, []), ?assertEqual( iolist_to_binary(Data), diff --git a/apps/emqx_utils/src/emqx_utils.app.src b/apps/emqx_utils/src/emqx_utils.app.src index 893ad707e..76d503331 100644 --- a/apps/emqx_utils/src/emqx_utils.app.src +++ b/apps/emqx_utils/src/emqx_utils.app.src @@ -2,7 +2,7 @@ {application, emqx_utils, [ {description, "Miscellaneous utilities for EMQX apps"}, % strict semver, bump manually! - {vsn, "5.0.13"}, + {vsn, "5.0.14"}, {modules, [ emqx_utils, emqx_utils_api, diff --git a/apps/emqx_utils/src/emqx_utils.erl b/apps/emqx_utils/src/emqx_utils.erl index fd9f5a311..3e7d28da1 100644 --- a/apps/emqx_utils/src/emqx_utils.erl +++ b/apps/emqx_utils/src/emqx_utils.erl @@ -64,7 +64,8 @@ tcp_keepalive_opts/4, format/1, format_mfal/1, - call_first_defined/1 + call_first_defined/1, + ntoa/1 ]). -export([ @@ -1053,6 +1054,15 @@ flatcomb(Ys = [_ | _], Zs = [_ | _]) -> flatcomb(Y, Zs) -> [Y | Zs]. +%% @doc Format IP address tuple or {IP, Port} tuple to string. +ntoa({IP, Port}) -> + ntoa(IP) ++ ":" ++ integer_to_list(Port); +ntoa({0, 0, 0, 0, 0, 16#ffff, AB, CD}) -> + %% v6 piggyback v4 + inet_parse:ntoa({AB bsr 8, AB rem 256, CD bsr 8, CD rem 256}); +ntoa(IP) -> + inet_parse:ntoa(IP). + -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). diff --git a/build b/build index c70f91b60..bbc053f01 100755 --- a/build +++ b/build @@ -387,10 +387,10 @@ docker_cleanup() { ## Build the default docker image based on debian 11. make_docker() { - local EMQX_BUILDER_VERSION="${EMQX_BUILDER_VERSION:-5.1-4}" + local EMQX_BUILDER_VERSION="${EMQX_BUILDER_VERSION:-5.2-8}" local EMQX_BUILDER_PLATFORM="${EMQX_BUILDER_PLATFORM:-debian11}" - local EMQX_BUILDER_OTP="${EMQX_BUILDER_OTP:-25.3.2-2}" - local EMQX_BUILDER_ELIXIR="${EMQX_BUILDER_ELIXIR:-1.14.5}" + local EMQX_BUILDER_OTP="${EMQX_BUILDER_OTP:-26.1.2-2}" + local EMQX_BUILDER_ELIXIR="${EMQX_BUILDER_ELIXIR:-1.15.7}" local EMQX_BUILDER=${EMQX_BUILDER:-ghcr.io/emqx/emqx-builder/${EMQX_BUILDER_VERSION}:${EMQX_BUILDER_ELIXIR}-${EMQX_BUILDER_OTP}-${EMQX_BUILDER_PLATFORM}} local EMQX_RUNNER="${EMQX_RUNNER:-${EMQX_DEFAULT_RUNNER}}" local EMQX_DOCKERFILE="${EMQX_DOCKERFILE:-deploy/docker/Dockerfile}" diff --git a/changes/ce/feat-12085.en.md b/changes/ce/feat-12085.en.md new file mode 100644 index 000000000..aa342f9c7 --- /dev/null +++ b/changes/ce/feat-12085.en.md @@ -0,0 +1 @@ +Upgrade to OTP 26.1.2-2 diff --git a/changes/ce/feat-12189.en.md b/changes/ce/feat-12189.en.md new file mode 100644 index 000000000..a8a1dab3a --- /dev/null +++ b/changes/ce/feat-12189.en.md @@ -0,0 +1,33 @@ +Enhanced JWT ACL Claim Format. + +The JWT ACL claim has been upgraded to support a more versatile format. +It now accepts an array structure, which resembles the file-based ACL rules. + +For example: + +```json +[ + { + "permission": "allow", + "action": "pub", + "topic": "${username}/#", + "qos": [0,1], + "retain": true + }, + { + "permission": "allow", + "action": "sub", + "topic": "eq ${username}/#", + "qos": [0,1] + }, + { + "permission": "deny", + "action": "all", + "topics": ["#"] + } +] +``` + +In this new format, when no matching rule is found, the action is not automatically denied. +This allows the authorization process to proceed to other configured authorization sources. +If no match is found throughout the chain, the final decision defers to the default permission set in `authorization.no_match`. diff --git a/changes/ee/feat-12072.en.md b/changes/ee/feat-12072.en.md new file mode 100644 index 000000000..0b91b5c45 --- /dev/null +++ b/changes/ee/feat-12072.en.md @@ -0,0 +1,3 @@ +Supports async query mode for GreptimeDB data bridge. It provides better performance. + + diff --git a/changes/ee/feat-12194.en.md b/changes/ee/feat-12194.en.md new file mode 100644 index 000000000..6d65fc5bd --- /dev/null +++ b/changes/ee/feat-12194.en.md @@ -0,0 +1 @@ +Improve Kafka producer performance. diff --git a/deploy/charts/emqx-enterprise/README.md b/deploy/charts/emqx-enterprise/README.md index d3977ceac..1d4898624 100644 --- a/deploy/charts/emqx-enterprise/README.md +++ b/deploy/charts/emqx-enterprise/README.md @@ -78,7 +78,8 @@ The following table lists the configurable parameters of the emqx chart and thei | `service.loadBalancerSourceRanges` | Address(es) that are allowed when service is LoadBalancer | [] | | `service.externalIPs` | ExternalIPs for the service | [] | | `service.externalTrafficPolicy` | External Traffic Policy for the service | `Cluster` -| `service.annotations` | Service annotations | {}(evaluated as a template) | +| `service.annotations` | Service/ServiceMonitor annotations | {}(evaluated as a template) | +| `service.labels` | Service/ServiceMontior labels | {}(evaluated as a template) | | `ingress.dashboard.enabled` | Enable ingress for EMQX Dashboard | false | | `ingress.dashboard.ingressClassName` | Set the ingress class for EMQX Dashboard | | | `ingress.dashboard.path` | Ingress path for EMQX Dashboard | / | diff --git a/deploy/charts/emqx-enterprise/templates/service-monitor.yaml b/deploy/charts/emqx-enterprise/templates/service-monitor.yaml index b37798a59..cb5c876d4 100644 --- a/deploy/charts/emqx-enterprise/templates/service-monitor.yaml +++ b/deploy/charts/emqx-enterprise/templates/service-monitor.yaml @@ -9,6 +9,9 @@ metadata: helm.sh/chart: {{ include "emqx.chart" . }} app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/managed-by: {{ .Release.Service }} + {{- if .Values.service.labels }} + {{- toYaml .Values.service.labels | nindent 4 }} + {{- end }} {{- if .Values.service.annotations }} annotations: {{- toYaml .Values.service.annotations | nindent 4 }} diff --git a/deploy/charts/emqx-enterprise/templates/service.yaml b/deploy/charts/emqx-enterprise/templates/service.yaml index 525390a90..1dd0e69f4 100644 --- a/deploy/charts/emqx-enterprise/templates/service.yaml +++ b/deploy/charts/emqx-enterprise/templates/service.yaml @@ -8,6 +8,9 @@ metadata: helm.sh/chart: {{ include "emqx.chart" . }} app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/managed-by: {{ .Release.Service }} + {{- if .Values.service.labels }} + {{- toYaml .Values.service.labels | nindent 4 }} + {{- end }} {{- if .Values.service.annotations }} annotations: {{- toYaml .Values.service.annotations | nindent 4 }} diff --git a/deploy/charts/emqx-enterprise/values.yaml b/deploy/charts/emqx-enterprise/values.yaml index e830b81af..9969f23cd 100644 --- a/deploy/charts/emqx-enterprise/values.yaml +++ b/deploy/charts/emqx-enterprise/values.yaml @@ -190,6 +190,7 @@ service: ## Provide any additional annotations which may be required. Evaluated as a template ## annotations: {} + labels: {} nodeSelector: {} diff --git a/deploy/charts/emqx/README.md b/deploy/charts/emqx/README.md index d9e144f0c..010156eda 100644 --- a/deploy/charts/emqx/README.md +++ b/deploy/charts/emqx/README.md @@ -79,7 +79,8 @@ The following table lists the configurable parameters of the emqx chart and thei | `service.loadBalancerSourceRanges` | Address(es) that are allowed when service is LoadBalancer | [] | | `service.externalIPs` | ExternalIPs for the service | [] | | `service.externalTrafficPolicy` | External Traffic Policy for the service | `Cluster` -| `service.annotations` | Service annotations | {}(evaluated as a template) | +| `service.annotations` | Service/ServiceMonitor annotations | {}(evaluated as a template) | +| `service.labels` | Service/ServiceMontior labels | {}(evaluated as a template) | | `ingress.dashboard.enabled` | Enable ingress for EMQX Dashboard | false | | `ingress.dashboard.ingressClassName` | Set the ingress class for EMQX Dashboard | | | `ingress.dashboard.path` | Ingress path for EMQX Dashboard | / | diff --git a/deploy/charts/emqx/templates/service-monitor.yaml b/deploy/charts/emqx/templates/service-monitor.yaml index b37798a59..cb5c876d4 100644 --- a/deploy/charts/emqx/templates/service-monitor.yaml +++ b/deploy/charts/emqx/templates/service-monitor.yaml @@ -9,6 +9,9 @@ metadata: helm.sh/chart: {{ include "emqx.chart" . }} app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/managed-by: {{ .Release.Service }} + {{- if .Values.service.labels }} + {{- toYaml .Values.service.labels | nindent 4 }} + {{- end }} {{- if .Values.service.annotations }} annotations: {{- toYaml .Values.service.annotations | nindent 4 }} diff --git a/deploy/charts/emqx/templates/service.yaml b/deploy/charts/emqx/templates/service.yaml index 525390a90..1dd0e69f4 100644 --- a/deploy/charts/emqx/templates/service.yaml +++ b/deploy/charts/emqx/templates/service.yaml @@ -8,6 +8,9 @@ metadata: helm.sh/chart: {{ include "emqx.chart" . }} app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/managed-by: {{ .Release.Service }} + {{- if .Values.service.labels }} + {{- toYaml .Values.service.labels | nindent 4 }} + {{- end }} {{- if .Values.service.annotations }} annotations: {{- toYaml .Values.service.annotations | nindent 4 }} diff --git a/deploy/charts/emqx/values.yaml b/deploy/charts/emqx/values.yaml index 88cc6279f..2a2b91299 100644 --- a/deploy/charts/emqx/values.yaml +++ b/deploy/charts/emqx/values.yaml @@ -190,6 +190,7 @@ service: ## Provide any additional annotations which may be required. Evaluated as a template ## annotations: {} + labels: {} nodeSelector: {} diff --git a/deploy/docker/Dockerfile b/deploy/docker/Dockerfile index b2dfbb1f6..185b3d0ee 100644 --- a/deploy/docker/Dockerfile +++ b/deploy/docker/Dockerfile @@ -1,4 +1,4 @@ -ARG BUILD_FROM=ghcr.io/emqx/emqx-builder/5.1-4:1.14.5-25.3.2-2-debian11 +ARG BUILD_FROM=ghcr.io/emqx/emqx-builder/5.2-8:1.15.7-26.1.2-2-debian11 ARG RUN_FROM=public.ecr.aws/debian/debian:11-slim FROM ${BUILD_FROM} AS builder ARG DEBUG=0 diff --git a/mix.exs b/mix.exs index 6f88ef0b4..26617d54b 100644 --- a/mix.exs +++ b/mix.exs @@ -49,7 +49,7 @@ defmodule EMQXUmbrella.MixProject do {:redbug, github: "emqx/redbug", tag: "2.0.10"}, {:covertool, github: "zmstone/covertool", tag: "2.0.4.1", override: true}, {:typerefl, github: "ieQu1/typerefl", tag: "0.9.1", override: true}, - {:ehttpc, github: "emqx/ehttpc", tag: "0.4.11", override: true}, + {:ehttpc, github: "emqx/ehttpc", tag: "0.4.12", override: true}, {:gproc, github: "emqx/gproc", tag: "0.9.0.1", override: true}, {:jiffy, github: "emqx/jiffy", tag: "1.0.6", override: true}, {:cowboy, github: "emqx/cowboy", tag: "2.9.2", override: true}, @@ -77,9 +77,9 @@ defmodule EMQXUmbrella.MixProject do {:esasl, github: "emqx/esasl", tag: "0.2.0"}, {:jose, github: "potatosalad/erlang-jose", tag: "1.11.2"}, # in conflict by ehttpc and emqtt - {:gun, github: "emqx/gun", tag: "1.3.9", override: true}, + {:gun, github: "emqx/gun", tag: "1.3.10", override: true}, # in conflict by emqx_connector and system_monitor - {:epgsql, github: "emqx/epgsql", tag: "4.7.0.1", override: true}, + {:epgsql, github: "emqx/epgsql", tag: "4.7.1.1", override: true}, # in conflict by emqx and observer_cli {:recon, github: "ferd/recon", tag: "2.5.1", override: true}, {:jsx, github: "talentdeficit/jsx", tag: "v3.1.0", override: true}, @@ -97,11 +97,13 @@ defmodule EMQXUmbrella.MixProject do {:hackney, github: "emqx/hackney", tag: "1.18.1-1", override: true}, # set by hackney (dependency) {:ssl_verify_fun, "1.1.7", override: true}, + {:rfc3339, github: "emqx/rfc3339", tag: "0.2.3", override: true}, + {:bcrypt, github: "emqx/erlang-bcrypt", tag: "0.6.1", override: true}, {:uuid, github: "okeuday/uuid", tag: "v2.0.6", override: true}, {:quickrand, github: "okeuday/quickrand", tag: "v2.0.6", override: true} ] ++ emqx_apps(profile_info, version) ++ - enterprise_deps(profile_info) ++ bcrypt_dep() ++ jq_dep() ++ quicer_dep() + enterprise_deps(profile_info) ++ jq_dep() ++ quicer_dep() end defp emqx_apps(profile_info, version) do @@ -198,7 +200,7 @@ defmodule EMQXUmbrella.MixProject do [ {:hstreamdb_erl, github: "hstreamdb/hstreamdb_erl", tag: "0.4.5+v0.16.1"}, {:influxdb, github: "emqx/influxdb-client-erl", tag: "1.1.11", override: true}, - {:wolff, github: "kafka4beam/wolff", tag: "1.8.0"}, + {:wolff, github: "kafka4beam/wolff", tag: "1.9.1"}, {:kafka_protocol, github: "kafka4beam/kafka_protocol", tag: "4.1.3", override: true}, {:brod_gssapi, github: "kafka4beam/brod_gssapi", tag: "v0.1.1"}, {:brod, github: "kafka4beam/brod", tag: "3.16.8"}, @@ -206,7 +208,7 @@ defmodule EMQXUmbrella.MixProject do {:crc32cer, "0.1.8", override: true}, {:supervisor3, "1.1.12", override: true}, {:opentsdb, github: "emqx/opentsdb-client-erl", tag: "v0.5.1", override: true}, - {:greptimedb, github: "GreptimeTeam/greptimedb-client-erl", tag: "v0.1.2", override: true}, + {:greptimedb, github: "GreptimeTeam/greptimedb-client-erl", tag: "v0.1.6", override: true}, # The following two are dependencies of rabbit_common. They are needed here to # make mix not complain about conflicting versions {:thoas, github: "emqx/thoas", tag: "v1.0.0", override: true}, @@ -214,12 +216,12 @@ defmodule EMQXUmbrella.MixProject do github: "emqx/credentials-obfuscation", tag: "v3.2.0", override: true}, {:rabbit_common, github: "emqx/rabbitmq-server", - tag: "v3.11.13-emqx", + tag: "v3.11.13.2", sparse: "deps/rabbit_common", override: true}, {:amqp_client, github: "emqx/rabbitmq-server", - tag: "v3.11.13-emqx", + tag: "v3.11.13.2", sparse: "deps/amqp_client", override: true} ] @@ -373,10 +375,8 @@ defmodule EMQXUmbrella.MixProject do %{ mnesia_rocksdb: enable_rocksdb?(), quicer: enable_quicer?(), - bcrypt: enable_bcrypt?(), jq: enable_jq?(), - observer: is_app?(:observer), - os_mon: enable_os_mon?() + observer: is_app?(:observer) } |> Enum.reject(&elem(&1, 1)) |> Enum.map(&elem(&1, 0)) @@ -785,12 +785,6 @@ defmodule EMQXUmbrella.MixProject do defp emqx_schema_mod(:enterprise), do: :emqx_enterprise_schema defp emqx_schema_mod(:community), do: :emqx_conf_schema - defp bcrypt_dep() do - if enable_bcrypt?(), - do: [{:bcrypt, github: "emqx/erlang-bcrypt", tag: "0.6.1", override: true}], - else: [] - end - defp jq_dep() do if enable_jq?(), do: [{:jq, github: "emqx/jq", tag: "v0.3.12", override: true}], @@ -804,35 +798,25 @@ defmodule EMQXUmbrella.MixProject do else: [] end - defp enable_bcrypt?() do - not win32?() - end - - defp enable_os_mon?() do - not win32?() - end - defp enable_jq?() do not Enum.any?([ - build_without_jq?(), - win32?() - ]) or "1" == System.get_env("BUILD_WITH_JQ") + build_without_jq?() + ]) end defp enable_quicer?() do - not Enum.any?([ - build_without_quic?(), - win32?(), - centos6?(), - macos?() - ]) or "1" == System.get_env("BUILD_WITH_QUIC") + "1" == System.get_env("BUILD_WITH_QUIC") or + not Enum.any?([ + macos?(), + build_without_quic?() + ]) end defp enable_rocksdb?() do not Enum.any?([ - build_without_rocksdb?(), - raspbian?() - ]) or "1" == System.get_env("BUILD_WITH_ROCKSDB") + raspbian?(), + build_without_rocksdb?() + ]) end defp pkg_vsn() do @@ -847,19 +831,6 @@ defmodule EMQXUmbrella.MixProject do String.trim(str) end - defp win32?(), - do: match?({:win_32, _}, :os.type()) - - defp centos6?() do - case File.read("/etc/centos-release") do - {:ok, "CentOS release 6" <> _} -> - true - - _ -> - false - end - end - defp macos?() do {:unix, :darwin} == :os.type() end diff --git a/rebar.config b/rebar.config index ffdc5472a..47151181c 100644 --- a/rebar.config +++ b/rebar.config @@ -64,8 +64,8 @@ , {covertool, {git, "https://github.com/zmstone/covertool", {tag, "2.0.4.1"}}} , {gpb, "4.19.9"} , {typerefl, {git, "https://github.com/ieQu1/typerefl", {tag, "0.9.1"}}} - , {gun, {git, "https://github.com/emqx/gun", {tag, "1.3.9"}}} - , {ehttpc, {git, "https://github.com/emqx/ehttpc", {tag, "0.4.11"}}} + , {gun, {git, "https://github.com/emqx/gun", {tag, "1.3.10"}}} + , {ehttpc, {git, "https://github.com/emqx/ehttpc", {tag, "0.4.12"}}} , {gproc, {git, "https://github.com/emqx/gproc", {tag, "0.9.0.1"}}} , {jiffy, {git, "https://github.com/emqx/jiffy", {tag, "1.0.6"}}} , {cowboy, {git, "https://github.com/emqx/cowboy", {tag, "2.9.2"}}} @@ -96,6 +96,8 @@ , {jsone, {git, "https://github.com/emqx/jsone.git", {tag, "1.7.1"}}} , {uuid, {git, "https://github.com/okeuday/uuid.git", {tag, "v2.0.6"}}} , {ssl_verify_fun, "1.1.7"} + , {rfc3339, {git, "https://github.com/emqx/rfc3339.git", {tag, "0.2.3"}}} + , {bcrypt, {git, "https://github.com/emqx/erlang-bcrypt.git", {tag, "0.6.1"}}} ]}. {xref_ignores, diff --git a/rebar.config.erl b/rebar.config.erl index 6958ad784..76a1f824b 100644 --- a/rebar.config.erl +++ b/rebar.config.erl @@ -35,9 +35,6 @@ assert_otp() -> ok end. -bcrypt() -> - {bcrypt, {git, "https://github.com/emqx/erlang-bcrypt.git", {tag, "0.6.1"}}}. - quicer() -> {quicer, {git, "https://github.com/emqx/quic.git", {tag, "0.0.308"}}}. @@ -47,8 +44,7 @@ jq() -> deps(Config) -> {deps, OldDeps} = lists:keyfind(deps, 1, Config), MoreDeps = - [bcrypt() || provide_bcrypt_dep()] ++ - [jq() || is_jq_supported()] ++ + [jq() || is_jq_supported()] ++ [quicer() || is_quicer_supported()], lists:keystore(deps, 1, Config, {deps, OldDeps ++ MoreDeps}). @@ -121,45 +117,41 @@ is_community_umbrella_app("apps/emqx_gateway_jt808") -> false; is_community_umbrella_app("apps/emqx_bridge_syskeeper") -> false; is_community_umbrella_app(_) -> true. +%% BUILD_WITHOUT_JQ +%% BUILD_WITHOUT_QUIC +%% BUILD_WITHOUT_ROCKSDB +is_build_without(Name) -> + "1" =:= os:getenv("BUILD_WITHOUT_" ++ Name). + +%% BUILD_WITH_QUIC +is_build_with(Name) -> + "1" =:= os:getenv("BUILD_WITH_" ++ Name). + is_jq_supported() -> - not (false =/= os:getenv("BUILD_WITHOUT_JQ") orelse - is_win32()) orelse - "1" == os:getenv("BUILD_WITH_JQ"). + not is_build_without("JQ"). is_quicer_supported() -> - not (false =/= os:getenv("BUILD_WITHOUT_QUIC") orelse - is_macos() orelse - is_win32() orelse is_centos_6()) orelse - "1" == os:getenv("BUILD_WITH_QUIC"). + %% for ones who want to build QUIC on macos + %% export BUILD_WITH_QUIC=1 + is_build_with("QUIC") orelse + is_quicer_supported(os:type()). + +is_quicer_supported({unix, darwin}) -> + %% no quic on macos so far + false; +is_quicer_supported(_) -> + not is_build_without("QUIC"). is_rocksdb_supported() -> - not (false =/= os:getenv("BUILD_WITHOUT_ROCKSDB") orelse - is_raspbian()) orelse - "1" == os:getenv("BUILD_WITH_ROCKSDB"). + %% there is no way one can build rocksdb on raspbian + %% so no need to check is_build_with + Distro = os_cmd("./scripts/get-distro.sh"), + is_rocksdb_supported(Distro). -is_macos() -> - {unix, darwin} =:= os:type(). - -is_centos_6() -> - %% reason: - %% glibc is too old - case file:read_file("/etc/centos-release") of - {ok, <<"CentOS release 6", _/binary>>} -> - true; - _ -> - false - end. - -is_raspbian() -> - case os_cmd("./scripts/get-distro.sh") of - "raspbian" ++ _ -> - true; - _ -> - false - end. - -is_win32() -> - win32 =:= element(1, os:type()). +is_rocksdb_supported("respbian" ++ _) -> + false; +is_rocksdb_supported(_) -> + not is_build_without("ROCKSDB"). project_app_dirs() -> project_app_dirs(get_edition_from_profile_env()). @@ -421,14 +413,12 @@ relx_apps(ReleaseType, Edition) -> [{App, load} || App <- BusinessApps]), lists:foldl(fun proplists:delete/2, Apps, excluded_apps(ReleaseType)). -excluded_apps(ReleaseType) -> +excluded_apps(_ReleaseType) -> OptionalApps = [ {quicer, is_quicer_supported()}, - {bcrypt, provide_bcrypt_release(ReleaseType)}, {jq, is_jq_supported()}, {observer, is_app(observer)}, - {mnesia_rocksdb, is_rocksdb_supported()}, - {os_mon, provide_os_mon_release()} + {mnesia_rocksdb, is_rocksdb_supported()} ], [App || {App, false} <- OptionalApps]. @@ -531,15 +521,6 @@ is_debug(VarName) -> _ -> true end. -provide_bcrypt_dep() -> - not is_win32(). - -provide_os_mon_release() -> - not is_win32(). - -provide_bcrypt_release(ReleaseType) -> - provide_bcrypt_dep() andalso ReleaseType =:= cloud. - erl_opts_i() -> [{i, "apps"}] ++ [{i, Dir} || Dir <- filelib:wildcard(filename:join(["apps", "*", "include"]))]. @@ -562,8 +543,7 @@ dialyzer(Config) -> AppsToExclude = AppNames -- KnownApps, Extra = - [os_mon, system_monitor, covertool] ++ - [bcrypt || provide_bcrypt_dep()] ++ + [system_monitor, tools, covertool] ++ [jq || is_jq_supported()] ++ [quicer || is_quicer_supported()], NewDialyzerConfig = diff --git a/rel/i18n/emqx_authn_jwt_schema.hocon b/rel/i18n/emqx_authn_jwt_schema.hocon index cd0af6f42..4251358d8 100644 --- a/rel/i18n/emqx_authn_jwt_schema.hocon +++ b/rel/i18n/emqx_authn_jwt_schema.hocon @@ -1,7 +1,31 @@ emqx_authn_jwt_schema { acl_claim_name.desc: -"""JWT claim name to use for getting ACL rules.""" +"""The JWT claim designated for accessing ACL (Access Control List) rules can be specified, +such as using the `acl` claim. A typical decoded JWT with this claim might appear as: +`{"username": "user1", "acl": ...}`. + +Supported ACL Rule Formats: + +- Object Format: + Utilizes action types pub (publish), sub (subscribe), or all (both publish and subscribe). + The value is a list of topic filters. + Example: `{"pub": ["topic1"], "sub": [], "all": ["${username}/#"]}`. + This example signifies that the token owner can publish to topic1 and perform both publish and subscribe + actions on topics starting with their username. + Note: In this format, if no topic matches, the action is denied, and the authorization process terminates. + +- Array Format (resembles File-Based ACL Rules): + Example: `[{"permission": "allow", "action": "all", "topic": "${username}/#"}]`. + Additionally, the `pub` or `publish` action rules can be extended with `qos` and `retain` field, + and `sub` or `subscribe` action rules can be extended with a `qos` field. + Note: Here, if no rule matches, the action is not immediately denied. + The process continues to other configured authorization sources, + and ultimately falls back to the default permission in config `authorization.no_match`. + +The ACL claim utilizes MQTT topic wildcard matching rules for publishing or subscribing. +A special syntax for the 'subscribe' action allows the use of `eq` for an exact match. +For instance, `eq t/#` permits or denies subscription to `t/#`, but not to `t/1`.""" acl_claim_name.label: """ACL claim name""" diff --git a/scripts/buildx.sh b/scripts/buildx.sh index 662a7233c..39d8b8e5e 100755 --- a/scripts/buildx.sh +++ b/scripts/buildx.sh @@ -9,7 +9,7 @@ ## example: ## ./scripts/buildx.sh --profile emqx --pkgtype tgz --arch arm64 \ -## --builder ghcr.io/emqx/emqx-builder/5.1-4:1.14.5-25.3.2-2-debian11 +## --builder ghcr.io/emqx/emqx-builder/5.2-8:1.15.7-26.1.2-2-debian11 set -euo pipefail @@ -24,7 +24,7 @@ help() { echo "--arch amd64|arm64: Target arch to build the EMQX package for" echo "--src_dir : EMQX source code in this dir, default to PWD" echo "--builder : Builder image to pull" - echo " E.g. ghcr.io/emqx/emqx-builder/5.1-4:1.14.5-25.3.2-2-debian11" + echo " E.g. ghcr.io/emqx/emqx-builder/5.2-8:1.15.7-26.1.2-2-debian11" } die() { diff --git a/scripts/pr-sanity-checks.sh b/scripts/pr-sanity-checks.sh index 19321230b..f22677cfa 100755 --- a/scripts/pr-sanity-checks.sh +++ b/scripts/pr-sanity-checks.sh @@ -12,9 +12,9 @@ if ! type "yq" > /dev/null; then exit 1 fi -EMQX_BUILDER_VERSION=${EMQX_BUILDER_VERSION:-5.1-4} -EMQX_BUILDER_OTP=${EMQX_BUILDER_OTP:-25.3.2-2} -EMQX_BUILDER_ELIXIR=${EMQX_BUILDER_ELIXIR:-1.14.5} +EMQX_BUILDER_VERSION=${EMQX_BUILDER_VERSION:-5.2-8} +EMQX_BUILDER_OTP=${EMQX_BUILDER_OTP:-26.1.2-2} +EMQX_BUILDER_ELIXIR=${EMQX_BUILDER_ELIXIR:-1.15.7} EMQX_BUILDER_PLATFORM=${EMQX_BUILDER_PLATFORM:-ubuntu22.04} EMQX_BUILDER=${EMQX_BUILDER:-ghcr.io/emqx/emqx-builder/${EMQX_BUILDER_VERSION}:${EMQX_BUILDER_ELIXIR}-${EMQX_BUILDER_OTP}-${EMQX_BUILDER_PLATFORM}} diff --git a/scripts/relup-test/start-relup-test-cluster.sh b/scripts/relup-test/start-relup-test-cluster.sh index 2cee1394e..afd296152 100755 --- a/scripts/relup-test/start-relup-test-cluster.sh +++ b/scripts/relup-test/start-relup-test-cluster.sh @@ -22,7 +22,7 @@ WEBHOOK="webhook.$NET" BENCH="bench.$NET" COOKIE='this-is-a-secret' ## Erlang image is needed to run webhook server and emqtt-bench -ERLANG_IMAGE="ghcr.io/emqx/emqx-builder/5.1-4:1.14.5-25.3.2-2-ubuntu20.04" +ERLANG_IMAGE="ghcr.io/emqx/emqx-builder/5.2-8:1.15.7-26.1.2-2-ubuntu22.04" # builder has emqtt-bench installed BENCH_IMAGE="$ERLANG_IMAGE"