Compare commits

...

1596 Commits

Author SHA1 Message Date
Ivan Dyachkov bcd63344b8
Merge pull request #13583 from id/20240807-sync-release-branches
sync release branches
2024-08-07 11:38:14 +02:00
Ivan Dyachkov cc3b26a3ac Merge remote-tracking branch 'upstream/release-58' into 20240807-sync-release-branches 2024-08-07 09:48:38 +02:00
Ivan Dyachkov dd686c24a0 Merge remote-tracking branch 'upstream/release-57' into 20240807-sync-release-branches 2024-08-07 09:44:38 +02:00
Ivan Dyachkov 592c4e0045
Merge pull request #12774 from emqx/dependabot/github_actions/dot-github/actions/package-macos/actions-package-macos-83d1e47aa6
chore(deps): bump the actions-package-macos group in /.github/actions/package-macos with 1 update
2024-08-07 09:43:53 +02:00
Ivan Dyachkov 073e3ea0a8
Merge pull request #13569 from emqx/dependabot/github_actions/actions-ef71aea555
chore(deps): bump the actions group across 1 directory with 8 updates
2024-08-07 09:35:52 +02:00
Xinyu Liu 81978ceaeb
Merge pull request #13571 from terry-xiaoyu/fast_fail_on_invalid_ssl_opts
chore: update esockd to 5.12.0
2024-08-07 11:21:32 +08:00
Ilia Averianov 6bfddd9952
Merge pull request #13565 from savonarola/0801-shared-subs-compact-structures
Reduce size of shared sub protocol structures
2024-08-06 19:56:08 +03:00
Thales Macedo Garitezi cf608a73a5
Merge pull request #13578 from thalesmg/20240806-r58-port-raft-precond
feat(dsraft): support atomic batches + preconditions (release-58)
2024-08-06 13:40:46 -03:00
Thales Macedo Garitezi a8200fb83d
Merge pull request #13579 from thalesmg/20240806-r58-test-flaky-consumer-rebalance
test: attempt to reduce test flakiness
2024-08-06 13:33:46 -03:00
Ilya Averyanov 9ad65c6ac1 feat(queue): reduce logging levels 2024-08-06 18:45:15 +03:00
Thales Macedo Garitezi 9ca3985bbd test: attempt to reduce test flakiness 2024-08-06 12:44:51 -03:00
Ilya Averyanov e17becb84d feat(queue): compact protocol structures, organize formatting 2024-08-06 18:05:02 +03:00
Andrew Mayorov 5dd8fefded test(ds): avoid side effects in check phase 2024-08-06 11:43:12 -03:00
Andrew Mayorov 7b85faf12a chore(dsraft): fix few spelling errors
Co-Authored-By: Thales Macedo Garitezi <thalesmg@gmail.com>
2024-08-06 11:43:12 -03:00
Andrew Mayorov b0594271b2 chore(dsraft): fix a typespec 2024-08-06 11:43:12 -03:00
Andrew Mayorov d8aa39a310 fix(dsraft): use local application environment 2024-08-06 11:43:12 -03:00
Andrew Mayorov fc0434afc8 chore(dslocal): refine few typespecs 2024-08-06 11:43:12 -03:00
Andrew Mayorov 5502af18b7 feat(ds): support deletions + precondition-related API in bitfield-lts 2024-08-06 11:43:12 -03:00
Andrew Mayorov 9f96e0957e test(ds): verify deletions work predictably 2024-08-06 11:43:12 -03:00
Andrew Mayorov 109ffe7a70 fix(dsbackend): unify timestamp resolution in operations / preconditions 2024-08-06 11:43:12 -03:00
Andrew Mayorov 1559aac486 test(dsbackend): add shared tests for atomic batches + preconditions 2024-08-06 11:43:12 -03:00
Andrew Mayorov 68990f1538 feat(ds): support operations + preconditions in skipstream-lts 2024-08-06 11:43:12 -03:00
Andrew Mayorov 5356d678cc feat(dsraft): support atomic batches + preconditions 2024-08-06 11:43:12 -03:00
Andrew Mayorov 11951f8f6c feat(ds): adopt buffer interface to `emqx_ds:operation()` 2024-08-06 11:43:12 -03:00
Andrew Mayorov 0aa4cdbaf3 feat(ds): add generic preconditions implementation 2024-08-06 11:43:12 -03:00
Ivan Dyachkov 281f8ddc83
Merge pull request #13575 from Kinplemelon/kinple/upgrade-dashboard-58
chore(dashboard): bump dashboard version to v1.10.0-beta.1 & e1.8.0-beta.1
2024-08-06 16:39:06 +02:00
Kinplemelon b80513e941 ci: update emqx docs link in dashboard 2024-08-06 15:21:19 +02:00
Ivan Dyachkov 822ed71282 chore: release 5.7.2 2024-08-06 13:25:56 +02:00
Kinple b8fd5de2a5
Merge pull request #13577 from Kinplemelon/kinple/upgrade-dashboard
chore(dashboard): bump dashboard version to v1.9.2 & e1.7.2
2024-08-06 19:02:50 +08:00
Kinplemelon 3ee84d60ae chore(dashboard): bump dashboard version to v1.9.2 & e1.7.2 2024-08-06 18:11:35 +08:00
Andrew Mayorov 3b52b658cd
Merge pull request #13559 from keynslug/feat/EMQX-12309/raft-precond
feat(dsraft): support atomic batches + preconditions
2024-08-06 09:17:16 +02:00
Kinplemelon cba3dcbeda chore(dashboard): bump dashboard version to v1.10.0-beta.1 & e1.8.0-beta.1 2024-08-06 13:44:16 +08:00
Kinple caf1897979
Merge pull request #13574 from Kinplemelon/kinple/upgrade-dashboard
chore(dashboard): bump dashboard version to e1.7.2-beta.7
2024-08-06 10:51:03 +08:00
Kinplemelon dbbd5e1458 ci: update emqx docs link in dashboard 2024-08-06 09:33:20 +08:00
Kinplemelon 0ab31df9d2 chore(dashboard): bump dashboard version to v1.9.2-beta.1 & e1.7.2-beta.7 2024-08-06 09:32:17 +08:00
Thales Macedo Garitezi 613fc644f5
Merge pull request #13425 from kjellwinblad/kjell/review_connector_error_logs_mqtt_etc/EMQX-12555/EMQX-12657
fix: make MQTT connector error log messages easier to understand
2024-08-05 17:34:13 -03:00
Andrew Mayorov b1a53568d6
test(ds): avoid side effects in check phase 2024-08-05 16:34:17 +02:00
Ivan Dyachkov d6651a1889
Merge pull request #13572 from id/20240805-prep-5.8.0-alpha.1
chore: prepare 5.8.0-alpha.1
2024-08-05 16:05:42 +02:00
Ivan Dyachkov 4cf7151139 chore: prepare 5.8.0-alpha.1 2024-08-05 11:09:07 +02:00
Ivan Dyachkov 4865999606 Merge remote-tracking branch 'upstream/master' into release-58 2024-08-05 10:59:59 +02:00
Andrew Mayorov 382feab7d1
chore(dsraft): fix few spelling errors
Co-Authored-By: Thales Macedo Garitezi <thalesmg@gmail.com>
2024-08-05 10:55:49 +02:00
Andrew Mayorov 6aad774075
chore(dsraft): fix a typespec 2024-08-05 10:55:49 +02:00
Andrew Mayorov 649cbf1c79
fix(dsraft): use local application environment 2024-08-05 10:55:49 +02:00
Andrew Mayorov 4cde5e98a3
chore(dslocal): refine few typespecs 2024-08-05 10:55:48 +02:00
Andrew Mayorov d631b5b296
feat(ds): support deletions + precondition-related API in bitfield-lts 2024-08-05 10:55:48 +02:00
Andrew Mayorov 26ec69d5f4
test(ds): verify deletions work predictably 2024-08-05 10:55:48 +02:00
Andrew Mayorov 58b9ab0210
fix(dsbackend): unify timestamp resolution in operations / preconditions 2024-08-05 10:55:22 +02:00
lafirest 4644072fd8
Merge pull request #13570 from lafirest/fix/api_key_bootstrap
fix(api_key): do not crash boot when the bootstrap file is not exists
2024-08-05 16:33:43 +08:00
Shawn bd87e3ce2b chore: update esockd to 5.12.0 2024-08-05 16:18:04 +08:00
firest c9c4d1a196 fix(api_key): do not crash boot when the bootstrap file is not exists 2024-08-05 15:56:05 +08:00
dependabot[bot] 11546b72f4
chore(deps): bump the actions group across 1 directory with 8 updates
Bumps the actions group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [actions/checkout](https://github.com/actions/checkout) | `4.1.2` | `4.1.7` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `4.3.3` | `4.3.5` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `4.1.7` | `4.1.8` |
| [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) | `3.0.0` | `3.2.0` |
| [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) | `3.3.0` | `3.6.1` |
| [docker/login-action](https://github.com/docker/login-action) | `3.2.0` | `3.3.0` |
| [erlef/setup-beam](https://github.com/erlef/setup-beam) | `1.18.0` | `1.18.1` |
| [ossf/scorecard-action](https://github.com/ossf/scorecard-action) | `2.3.3` | `2.4.0` |



Updates `actions/checkout` from 4.1.2 to 4.1.7
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4.1.2...692973e3d937129bcbf40652eb9f2f61becf3332)

Updates `actions/upload-artifact` from 4.3.3 to 4.3.5
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](65462800fd...89ef406dd8)

Updates `actions/download-artifact` from 4.1.7 to 4.1.8
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](65a9edc588...fa0a91b85d)

Updates `docker/setup-qemu-action` from 3.0.0 to 3.2.0
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](68827325e0...49b3bc8e6b)

Updates `docker/setup-buildx-action` from 3.3.0 to 3.6.1
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](d70bba72b1...988b5a0280)

Updates `docker/login-action` from 3.2.0 to 3.3.0
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](0d4c9c5ea7...9780b0c442)

Updates `erlef/setup-beam` from 1.18.0 to 1.18.1
- [Release notes](https://github.com/erlef/setup-beam/releases)
- [Commits](a6e26b2231...b9c58b0450)

Updates `ossf/scorecard-action` from 2.3.3 to 2.4.0
- [Release notes](https://github.com/ossf/scorecard-action/releases)
- [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md)
- [Commits](dc50aa9510...62b2cac7ed)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: docker/setup-qemu-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: docker/setup-buildx-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: docker/login-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: erlef/setup-beam
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: ossf/scorecard-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-05 03:25:47 +00:00
dependabot[bot] bcb70a9fb9
chore(deps): bump the actions-package-macos group
Bumps the actions-package-macos group in /.github/actions/package-macos with 1 update: [actions/cache](https://github.com/actions/cache).


Updates `actions/cache` from 4.0.1 to 4.0.2
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](ab5e6d0c87...0c45773b62)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions-package-macos
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-05 03:17:26 +00:00
JimMoen 09ec31908b
Merge pull request #13357 from JimMoen/fix-utf8-frame-error-connack
Stop returning `CONNACK` or `DISCONNECT` to clients that sent malformed CONNECT packets.

- Only send `CONNACK` with reason code `frame_too_large` for MQTT-v5.0 when connecting if the protocol version field in CONNECT can be detected.
- Otherwise **DONOT** send any CONNACK or DISCONNECT packet.
2024-08-02 15:24:30 +08:00
lafirest b94ec4014f
Merge pull request #13563 from lafirest/fix/payload_encode
fix(log): respect payload encoding settings when formatting packets
2024-08-02 14:38:12 +08:00
firest 74c346f9d1 fix(log): respect payload encoding settings when formatting packets 2024-08-02 12:41:30 +08:00
zhongwencool 8a33ef8576
Merge pull request #13562 from zhongwencool/fix-deactivate-alarm
fix: deactivate alarm before create resource
2024-08-02 12:08:27 +08:00
zhongwencool 6c2033ecbf fix: deactivate alarm before create resource 2024-08-02 11:03:59 +08:00
zmstone 51530588ef ci: fix a typo in commented out docker-compose yaml file 2024-08-01 22:41:42 +02:00
Thales Macedo Garitezi bba9d085d6 test: refactor test structure 2024-08-01 16:03:04 -03:00
Thales Macedo Garitezi 3162fe7a27 feat: prettify some error explanations 2024-08-01 15:31:00 -03:00
Thales Macedo Garitezi 52b2d73b28 test: move new test to newer module and use current apis 2024-08-01 15:13:25 -03:00
Thales Macedo Garitezi 44e7f2e9b2 refactor: use macros for status to avoid typos 2024-08-01 14:49:43 -03:00
Thales Macedo Garitezi baf2b96cbc test: refactor test structure 2024-08-01 14:27:25 -03:00
Kjell Winblad ba2d4f3df3 docs: add change log entry 2024-08-01 14:21:27 -03:00
Kjell Winblad 11aaa7b07d fix: make MQTT connector error log messages easier to understand
Fixes:
https://emqx.atlassian.net/browse/EMQX-12555
https://emqx.atlassian.net/browse/EMQX-12657
2024-08-01 14:21:26 -03:00
Thales Macedo Garitezi 4250d01363
Merge pull request #13546 from thalesmg/20240730-r58-pulsar-query-mode
feat: expose `resource_opts.query_mode` for pulsar action
2024-08-01 14:19:16 -03:00
Thales Macedo Garitezi 86853ac6ef
Merge pull request #13545 from thalesmg/20240730-m-connector-jwt-app
refactor: move JWT worker and helpers to separate app
2024-08-01 13:06:27 -03:00
Andrew Mayorov 810a4d3cf9
test(dsbackend): add shared tests for atomic batches + preconditions 2024-08-01 14:26:45 +02:00
Andrew Mayorov 7b243ef7ad
feat(ds): support operations + preconditions in skipstream-lts 2024-08-01 14:26:45 +02:00
Andrew Mayorov fcf76d28ba
feat(dsraft): support atomic batches + preconditions 2024-08-01 14:26:45 +02:00
Andrew Mayorov 3b5d98c1d9
feat(ds): adopt buffer interface to `emqx_ds:operation()` 2024-08-01 14:26:45 +02:00
Andrew Mayorov 451b03ff99
feat(ds): add generic preconditions implementation 2024-08-01 14:26:45 +02:00
JimMoen f792418a68
Merge pull request #13552 from JimMoen/fix-plugin-app-takes-too-long
fix: add a startup timeout limit for the plugin application
2024-08-01 16:46:09 +08:00
JimMoen 4915cc0da6
chore: add changelog entry for 13357 2024-08-01 15:23:58 +08:00
JimMoen 15b3f4deb0
fix: rm unused func and exports 2024-08-01 15:00:24 +08:00
JimMoen 7a251c9ead
test: handle frame error for CONNECT packets 2024-08-01 10:26:31 +08:00
JimMoen 37a89d0094
fix: enrich parse_state and connection serialize opts 2024-08-01 10:26:31 +08:00
JimMoen c313aa89f0
fix: try throw proto_ver and proto_name when parsing CONNECT packet 2024-08-01 10:26:31 +08:00
JimMoen 6db1c0a446
refactor: separate function to handle `frame_error` 2024-08-01 10:26:31 +08:00
JimMoen d4508a4f1d
chore: sync master `elvis.config` 2024-08-01 10:26:31 +08:00
Thales Macedo Garitezi a6a9538e73 refactor: move JWT worker and helpers to separate app
Some bridge applications might need to use JWTs before the `emqx_connector` is started, so
we must move JWT table initialization to a separate dependency application.
2024-07-31 14:52:12 -03:00
Thales Macedo Garitezi 9f97bff7d0 feat: expose `resource_opts.query_mode` for pulsar action
Fixes https://emqx.atlassian.net/browse/EMQX-12782
2024-07-31 11:13:11 -03:00
Ivan Dyachkov 577f1a7d8a
Merge pull request #13553 from id/20240731-ci-fix-docker-build
ci: fix docker images build
2024-07-31 16:04:47 +02:00
Ivan Dyachkov e42021d314
Merge pull request #13554 from id/20240731-sync-release-57
sync release-57
2024-07-31 15:48:37 +02:00
Thales Macedo Garitezi 08c58cc319
Merge pull request #13543 from thalesmg/20240730-r57-sr-delete-protobuf-cache
fix(schema registry): clear protobuf code cache when deleting/updating serdes
2024-07-31 10:16:48 -03:00
Thales Macedo Garitezi 150fee87f1
Merge pull request #13541 from thalesmg/20240730-r57-unset-crl-check-listener
fix(crl): force remove CRL fields from SSL opts after listener update
2024-07-31 10:16:35 -03:00
ieQu1 6058b50c91
Merge pull request #13555 from ieQu1/ds-rest-404
fix(mgmt): Return 404 for /ds/ API endpoints when DS is disabled
2024-07-31 14:57:17 +02:00
Thales Macedo Garitezi 85cff5e7eb fix: merge conflicts 2024-07-31 09:14:29 -03:00
ieQu1 569f48f5a1
fix(mgmt): Return 404 for /ds/ API endpoints when DS is disabled 2024-07-31 13:44:38 +02:00
ieQu1 2cf86e76ee
Merge pull request #13551 from ieQu1/EMQX-12587
fix(sessds): Expose durable sessions in the config API
2024-07-31 12:00:26 +02:00
Ivan Dyachkov 74cef7937d Merge remote-tracking branch 'upstream/release-57' into 20240731-sync-release-57 2024-07-31 11:31:29 +02:00
JimMoen c658cfe269
fix: make static_check happy 2024-07-31 17:17:13 +08:00
JimMoen a246551914
fix: add a startup timeout limit for the plugin application 2024-07-31 17:17:11 +08:00
JimMoen b1c8bc2421
Merge pull request #13548 from JimMoen/feat-plugin-on-config-changed-callback
feat: call plugin's app module `on_config_changed/2` callback
2024-07-31 16:40:48 +08:00
ieQu1 200b5ab294
Merge pull request #13550 from ieQu1/no-ra-dependency-on-oss
chore(emqx): Remove ra from the list of EMQX dependencies
2024-07-31 10:30:44 +02:00
Ivan Dyachkov 8d8ff6cf5d ci: fix docker images build
/etc/docker/daemon.json requires root for read access
2024-07-31 10:27:04 +02:00
ieQu1 a23b8266b1
fix(sessds): Expose durable sessions in the config API 2024-07-31 10:18:38 +02:00
ieQu1 d69342a2fc
chore(emqx): Remove ra from the list of EMQX dependencies 2024-07-31 09:56:28 +02:00
JimMoen e6bfc14cc9
fix: try-catch optional `on_config_changed/2` plugin app callback 2024-07-31 10:09:02 +08:00
JimMoen 3d1f0c756c
feat: call plugin's app module `on_config_changed/2` callback
assume the module: `[PluginName]_app`
2024-07-31 10:09:02 +08:00
Thales Macedo Garitezi 83041a8b83
Merge pull request #13544 from thalesmg/20240730-m-test-flaky-client-v2
test(clients v2 api): attempt to reduce flakiness
2024-07-30 16:07:37 -03:00
Thales Macedo Garitezi 1c4402b12c test(clients v2 api): attempt to reduce flakiness
https://github.com/emqx/emqx/actions/runs/10161391242/job/28101183920#step:6:331
2024-07-30 14:07:08 -03:00
Thales Macedo Garitezi ebb69f4ebf fix(crl): force remove crl fields from SSL opts after listener update
Fixes https://emqx.atlassian.net/browse/EMQX-12785
2024-07-30 14:00:24 -03:00
Thales Macedo Garitezi fd961f9da7 fix(schema registry): clear protobuf code cache when deleting/updating serde
Fixes https://emqx.atlassian.net/browse/EMQX-12789
2024-07-30 13:52:34 -03:00
Ilia Averianov 359bc38aa4
Merge pull request #13407 from savonarola/0701-shared-sub
Implement shared subscriptions
2024-07-30 16:12:13 +03:00
Ilya Averyanov 08f70e4a25 feat(queue): move ds shared sub dependent test to emqx_ds_shared_sub app 2024-07-30 14:19:39 +03:00
Ilya Averyanov e408804efb feat(queue): fix dialyzer issues 2024-07-30 13:01:48 +03:00
Ilya Averyanov e294d35703 feat(queue): add schema descriptions 2024-07-30 13:01:48 +03:00
Ilya Averyanov 303ff95e10 feat(queue): add stub for CRUD API 2024-07-30 13:01:48 +03:00
Ilya Averyanov 23f0e88b45 feat(queue): add integration with external broker 2024-07-30 13:01:46 +03:00
Ilya Averyanov f0dd1bc4f4 feat(queue): add shared sub support to the management API 2024-07-30 13:01:20 +03:00
Ilya Averyanov 9b30320ddb feat(queue): simplify progress report on disconnect 2024-07-30 13:01:20 +03:00
Ilya Averyanov cae27293a5 feat(queue): move route registration to sessions 2024-07-30 13:01:19 +03:00
Ilya Averyanov 81f4103d60 feat(queue): avoid cyclic dependencies 2024-07-30 13:01:19 +03:00
Ilya Averyanov bab526be24 feat(queue): self-revoke all shared streams on session open 2024-07-30 13:01:19 +03:00
Ilya Averyanov 9307a82004 feat(queue): rearrange leader's code 2024-07-30 13:01:19 +03:00
Ilya Averyanov b8e8f7c8e0 feat(queue): add pre_renew_streams callback 2024-07-30 13:01:18 +03:00
Ilya Averyanov a97a0d6400 feat(queue): fix dialyzer issues 2024-07-30 13:01:18 +03:00
Ilya Averyanov 8705956cdc feat(queue): update docs 2024-07-30 13:01:18 +03:00
Ilya Averyanov f213569460 feat(queue): clarify naming; identify shared subs by full topic filter 2024-07-30 13:01:18 +03:00
Ilya Averyanov 7e23f8d19f feat(queue): fix include 2024-07-30 13:01:17 +03:00
Ilya Averyanov a676ede6b8 feat(queue): improve logging 2024-07-30 13:01:17 +03:00
Ilya Averyanov 9e5e7a23c5 feat(queue): remove unnecessary acked flag 2024-07-30 13:01:17 +03:00
Ilya Averyanov 143086b0ef feat(queue): replace invalid rewing algorithm with skipping iterator 2024-07-30 13:01:16 +03:00
Ilya Averyanov c569625dd1 feat(queue): handle partially unacked ranges 2024-07-30 13:01:16 +03:00
Ilya Averyanov 7daab1ab23 feat(queue): move replay progress to a separate data structure 2024-07-30 13:01:16 +03:00
Ilya Averyanov 077ee38530 feat(queue): add config 2024-07-30 13:01:15 +03:00
Ilya Averyanov b74189570d feat(queue): do not use ee app from emqx app 2024-07-30 13:01:15 +03:00
Ilya Averyanov 649cf88042 feat(queue): kick agents that do not return to the replaying state for long 2024-07-30 13:01:15 +03:00
Ilya Averyanov 1496f7f778 feat(queue): add leader_rank_progress test 2024-07-30 13:01:15 +03:00
Ilya Averyanov 91dd1183ad feat(queue): fix dialyzer issues 2024-07-30 13:01:14 +03:00
Ilya Averyanov 65ab81ff74 feat(queue): fix quick resubscription 2024-07-30 13:01:14 +03:00
Ilya Averyanov 53d4cd3174 feat(queue): rename leader' stream_progresses to stream_states 2024-07-30 13:01:14 +03:00
Ilya Averyanov 7d004b37da feat(queue): implement stream finalization 2024-07-30 13:01:13 +03:00
Ilya Averyanov e5547005eb feat(queue): implement resubscribe test 2024-07-30 13:01:13 +03:00
Ilya Averyanov fada2a3fea feat(queue): reorganize and document shared subs module 2024-07-30 13:01:13 +03:00
Ilya Averyanov b4a010d63b feat(queue): implement unsubscribe 2024-07-30 13:01:13 +03:00
Ilya Averyanov 9bde981c44 feat(queue): fix static check issues 2024-07-30 13:01:12 +03:00
Ilya Averyanov 7658e081c5 feat(queue): move design docs to the EIP 2024-07-30 13:01:12 +03:00
Ilya Averyanov 8dce530d15 feat(queue): fix progress reporting and more tests
We test reassignment during the intensive replay
2024-07-30 13:01:12 +03:00
Ilya Averyanov a20d262327 feat(queue): send progress before fetching new messages 2024-07-30 13:01:11 +03:00
Ilya Averyanov d32f282feb feat(queue): add graceful disconnect 2024-07-30 13:01:11 +03:00
Ilya Averyanov 1d728a05b2 feat(queue): send metadata with agent when connecting to leader
It will be used to attach agent taints to improve stream assignment.
2024-07-30 13:01:11 +03:00
Ilya Averyanov 49bff5c08a feat(queue): wrap remote calls in a proto 2024-07-30 13:01:10 +03:00
Ilya Averyanov 61eda0ff31 feat(queue): identify agents by SessionId in tests 2024-07-30 13:01:10 +03:00
Ilya Averyanov 8f0d807c00 feat(queue): add new test scenarios 2024-07-30 13:01:10 +03:00
Ilya Averyanov bceb5d43ed feat(queue): fix stream rebalancing issues, update tests 2024-07-30 13:01:10 +03:00
Ilya Averyanov 03fea34962 feat(queue): document protocol between agent and leader
Document leader's states
2024-07-30 13:01:09 +03:00
Ilya Averyanov 082514f557 feat(queue): implement full protocol between agent and leader 2024-07-30 13:01:09 +03:00
Ilya Averyanov c831f0772f feat(queue): handle renew_lease_timeout 2024-07-30 13:01:09 +03:00
Ivan Dyachkov ca455ad992
Merge pull request #13532 from emqx/sync-release-57-20240729-021938
Sync release-57
2024-07-30 10:49:09 +02:00
JianBo He c347c2c285
Merge pull request #13540 from zmstone/0729-rule-funciton-getenv-should-be-limited-to-vars-with-prefix-EMQXVAR_
refactor: force getenv to access only OS env with prefix EMQXVAR_
2024-07-30 08:23:24 +08:00
zmstone a49cd78aae refactor: force getenv to access only OS env with prefix EMQXVAR_ 2024-07-29 23:54:00 +02:00
zmstone 4065158be7
Merge pull request #13534 from JimMoen/feat-add-superuser-skip-authz
feat: add authz skipped trace for superuser
2024-07-29 22:30:13 +02:00
ieQu1 18721d05bc
Merge pull request #13526 from ieQu1/replicant-ee
fix(mria): Reserve replicant role for EE only
2024-07-29 22:10:06 +02:00
zmstone 7f7d0741d2
Merge pull request #13528 from zmstone/0726-unrecoverable-error-limit
0726 unrecoverable error limit
2024-07-29 21:32:14 +02:00
zmstone 2e39c4ad5e
Merge pull request #13495 from thalesmg/20240719-m-hide-enable-fields-mkII
chore: hide enable flags from schema and config examples
2024-07-29 21:31:20 +02:00
zmstone 5b50d5433a
Merge pull request #13537 from thalesmg/20240729-r57-auto-decode-payload-kprodu
feat: attempt to automatically decode `payload` similar to key and message templates
2024-07-29 21:03:41 +02:00
zmstone eab440e0c1 docs: add changelog for PR 13528 2024-07-29 20:41:57 +02:00
zmstone e08425e67d refactor(log-throttler): remove unnecessary code
there is no need to reset counters before erasing
2024-07-29 20:41:27 +02:00
zhongwencool f6f1d32da0 feat: throttle with resource_id 2024-07-29 20:41:27 +02:00
zhongwencool 2924ec582a feat: add unrecoverable_resource_error throttle 2024-07-29 20:41:27 +02:00
zhongwencool 8dc1d1424a chore: add resource tag for log 2024-07-29 20:41:27 +02:00
Thales Macedo Garitezi 693d5dd394 feat: attempt to automatically decode `payload` similar to key and message templates 2024-07-29 13:01:06 -03:00
ieQu1 f85db0a0e9
fix: Apply suggestions from code review
Co-authored-by: Thales Macedo Garitezi <thalesmg@gmail.com>
2024-07-29 17:22:41 +02:00
lafirest 60aefd1065
Merge pull request #13520 from lafirest/feat/scram-rest-acl
feat(scram): supports ACL rules in `scram_restapi` backend
2024-07-29 22:46:50 +08:00
JianBo He c637422302
Merge pull request #13518 from thalesmg/20240724-r57-dynamic-kprodu-action-mkIII
feat(kafka producer): allow dynamic topics (mkIII)
2024-07-29 22:43:20 +08:00
Thales Macedo Garitezi e80d43d14d test(fix): use ebin path without plugins
Without the filtering that already exists in cth:ebin_path, the rebar3 plugins path may
take priority over normal dependencies.  Since we just updated hocon, and there seems to
be an older hocon among the rebar3 plugins, it started to break the test because older
hocon was getting loaded in the peer.
2024-07-29 09:50:25 -03:00
Thales Macedo Garitezi b3074144cc chore: temporarily revert `NO_DOC` changes to fields with default value = false
These will be dealt with in follow up PRs, by allowing the parent struct to be set to a
special `disabled` value in such cases.
2024-07-29 09:50:25 -03:00
Thales Macedo Garitezi 6786c9b517
refactor: improve descriptions and identifiers
Co-authored-by: zmstone <zmstone@gmail.com>
2024-07-29 09:45:52 -03:00
Thales Macedo Garitezi 8913de10c0
Merge pull request #13527 from thalesmg/20240726-r57-multiple-froms-sql-test
fix(rule engine tester): fix message publish with bridge source in from clause
2024-07-29 09:37:17 -03:00
JimMoen 5ddd7d7a6a
test: superuser skipped all authz check 2024-07-29 17:27:36 +08:00
JimMoen d7cac74bed
feat: add authz skipped trace 2024-07-29 17:27:36 +08:00
JianBo He 0b0a28ae44
chore: update changes/ee/feat-13504.en.md
Co-authored-by: zmstone <zmstone@gmail.com>
2024-07-29 10:45:24 +08:00
id c1e2801f41 Merge remote-tracking branch 'origin/release-57' into sync-release-57-20240729-021938 2024-07-29 02:19:38 +00:00
ieQu1 8036baf22c
test(paho): Run RLOG paho test with replicants only on EE 2024-07-26 21:53:32 +02:00
ieQu1 268f887700
test(mgmt): Disable certain tests on OSS 2024-07-26 20:24:53 +02:00
Thales Macedo Garitezi 1d56ac6e5e refactor: change topic schema type 2024-07-26 14:26:21 -03:00
Thales Macedo Garitezi 4e0742c66f feat: make kafka producer freely dynamic 2024-07-26 14:25:20 -03:00
ieQu1 8c1302f455
test(conf_app): Remove redundand config 2024-07-26 17:25:09 +02:00
ieQu1 b8a2a8ea18
test(router): Skip certain tests on OSS 2024-07-26 17:25:09 +02:00
ieQu1 b7c424a13d
test(persmsg): Remove redundant config 2024-07-26 17:17:06 +02:00
ieQu1 1b6494ab9a
test(mgmt): Remove redundant config 2024-07-26 17:17:06 +02:00
ieQu1 41bf5cd6ca
test(otel): Remove redundant config 2024-07-26 17:17:06 +02:00
ieQu1 548bcceab7
test(auth): Remove redundant config 2024-07-26 17:17:06 +02:00
ieQu1 1beda1cd11
test(mria): Remove role from the example config 2024-07-26 17:17:06 +02:00
ieQu1 9da744c423
fix(mria): Reserve replicant role for EE only 2024-07-26 17:17:06 +02:00
lafirest b2f2af6871
Merge pull request #13523 from lafirest/fix/oidc
fix(oidc): fixed update and callback errors for OIDC
2024-07-26 21:09:11 +08:00
Thales Macedo Garitezi 3fae704903 fix(rule engine tester): fix message publish with bridge source in from clause
Fixes https://emqx.atlassian.net/browse/EMQX-12762
2024-07-26 09:27:16 -03:00
lafirest 2d6b2bff8e
Merge pull request #13524 from lafirest/feat/exclusive-cli
feat(exclusive): added CLI interface for exclusive topics
2024-07-26 19:54:03 +08:00
firest dc342a35ac chore: update changes 2024-07-26 17:18:52 +08:00
firest 397c104a85 feat(exclusive): added CLI interface for exclusive topics 2024-07-26 16:56:47 +08:00
firest 49b24a3049 fix(oidc): fixed update and callback errors for OIDC 2024-07-26 15:41:22 +08:00
firest 7bf70aaab6 feat(scram): supports ACL rules in `scram_restapi` backend 2024-07-26 14:30:28 +08:00
zmstone 9a5d50f26a
Merge pull request #13521 from zmstone/0725-add-ldap-reconnect-on-timeout
0725 add ldap reconnect on timeout
2024-07-26 08:29:02 +02:00
Thales Macedo Garitezi df1f4fad70 feat(kafka producer): allow dynamic topics from pre-configured topics
Fixes https://emqx.atlassian.net/browse/EMQX-12656
2024-07-25 15:33:12 -03:00
Thales Macedo Garitezi 39b8cb1789
Merge pull request #13487 from thalesmg/20240715-m-refactor-cluster-link-api
feat(cluster link): refactor http api, add status and metrics
2024-07-25 14:51:36 -03:00
Thales Macedo Garitezi 33eccb35da chore: update wolff -> 3.0.2 2024-07-25 14:30:50 -03:00
zmstone f6a0f56771 docs: add changelog for PR 13521 2024-07-25 19:24:52 +02:00
zmstone 7631420eef test: add test case to cover ldap search timeout 2024-07-25 18:43:37 +02:00
zmstone 8f94e9684c fix: handle ldap seqrch error 2024-07-25 18:42:09 +02:00
zmstone 43f799508a chore: add ldap test doc 2024-07-25 18:42:08 +02:00
Thales Macedo Garitezi 03821c7b49 fix(cluster link metrics): route count metric is cluster-wide 2024-07-25 13:12:08 -03:00
Thales Macedo Garitezi 6da71200f3 refactor: improve bookkeeping api 2024-07-25 13:12:08 -03:00
Thales Macedo Garitezi 6dbf015c93 refactor: demote hidden config to hardcoded value 2024-07-25 13:12:08 -03:00
Thales Macedo Garitezi 30259284d1 chore: namespace metrics by type 2024-07-25 13:12:08 -03:00
Thales Macedo Garitezi 87e4e2340d refactor: better metric and error fold 2024-07-25 13:12:08 -03:00
lafirest 1925ed2f55
Merge pull request #13507 from lafirest/feat/env_func
feat(variform): add a builtin function to get env vars
2024-07-25 22:46:50 +08:00
lafirest a45f817f0e
Merge pull request #13515 from lafirest/fix/exclusive
fix(exclusive): allow the same client to resubscribe to an existing exclusive topic
2024-07-25 21:26:08 +08:00
firest 57959ac7d4 chore: update changes 2024-07-25 18:59:40 +08:00
firest 79020b2436 feat(variform): add a builtin function to get env vars 2024-07-25 18:50:53 +08:00
firest 141d8144e4 fix(scram): change the name from `scram_http` to `scram_restapi` 2024-07-25 17:01:49 +08:00
firest 4f21594707 chore: update changes 2024-07-25 09:40:20 +08:00
firest 117c8197d7 fix(exclusive): allow the same client to resubscribe to an existing exclusive topic 2024-07-25 09:40:15 +08:00
Thales Macedo Garitezi b283a8c1ff
Merge pull request #13505 from thalesmg/20240722-m-rule-conn-deps-part-2
feat(rule engine api): add filters options for action and source ids
2024-07-24 16:52:47 -03:00
Thales Macedo Garitezi c728b98e79
Merge pull request #13510 from thalesmg/20240723-r57-fix-jwt-about-to-expire-check
fix(jwt): fix grace period for renewal check
2024-07-24 16:52:35 -03:00
Thales Macedo Garitezi dda73651c5 fix(cluster link metrics): use periodic full table scan and gauge to count routes 2024-07-24 16:46:04 -03:00
Ivan Dyachkov c31e28153f
Merge pull request #13513 from id/20240724-sync-release-57
sync release-57
2024-07-24 20:12:06 +02:00
Thales Macedo Garitezi 7829838dc5 feat(cluster link api): add forwarding resource metrics to response 2024-07-24 14:53:57 -03:00
Thales Macedo Garitezi 80e035f115 feat(rule engine api): add filters options for action and source ids
Fixes https://emqx.atlassian.net/browse/EMQX-12654 (requirement 2)
2024-07-24 13:32:50 -03:00
Thales Macedo Garitezi 34f5a886ce refactor(cluster link api): return erpc errors in status and metrics responses 2024-07-24 12:07:34 -03:00
Thales Macedo Garitezi 79db2e6d7f test: fix flaky test 2024-07-24 11:17:00 -03:00
Thales Macedo Garitezi 3e4eeddb78 fix: add missing `resource_type` callback implementations 2024-07-24 10:53:33 -03:00
Thales Macedo Garitezi d2da311416 fix(resource): create undocumented callback
Created by https://github.com/emqx/emqx/pull/13449 but not added as a callback.
2024-07-24 10:53:33 -03:00
Thales Macedo Garitezi 76e51fa532 fix: correctly use maybe match clause 2024-07-24 10:17:45 -03:00
Thales Macedo Garitezi 82bb876de0
docs: improve descriptions
Co-authored-by: Andrew Mayorov <encube.ul@gmail.com>
2024-07-24 10:15:01 -03:00
Thales Macedo Garitezi 2d507146ab refactor: change style of case clause 2024-07-24 10:13:48 -03:00
Thales Macedo Garitezi 216a6abed9 refactor: rename CRUD functions 2024-07-24 10:11:03 -03:00
Thales Macedo Garitezi ca2d4ad2a0 refactor: move metrics logic to separate module 2024-07-24 10:04:27 -03:00
Thales Macedo Garitezi 311419f621
Merge pull request #13489 from thalesmg/20240718-m-init-debug
feat(bin/emqx): add `-init_debug` system arg when `DEBUG=2`
2024-07-24 09:16:12 -03:00
Thales Macedo Garitezi 9a950571d8
Merge pull request #13492 from thalesmg/20240718-m-rules-conn-deps
feat: return dependent entities in connectors/actions/sources API
2024-07-24 09:16:00 -03:00
Thales Macedo Garitezi 9e65e0d048
Merge pull request #13503 from thalesmg/20240722-r57-resource-manager-hc-interval-startup
fix(connector resource): use configuration `resource_opts` for health check interval when starting up
2024-07-24 09:15:47 -03:00
ieQu1 d1edf8aad2
Merge pull request #13514 from ieQu1/skip-streams-improvement
fix(ds): Improve logic of skipstream LTS layout
2024-07-24 13:28:44 +02:00
ieQu1 b010efb647
fix(ds): Improve logic of skipstream LTS layout
Iterators:
Previously it used timestamp of the next message as a reference. This
won't work well for the upcoming beamformer/beamsplitter feature. This
commit changes the logic so iterators store timestamp of the last seen
message.

Cooked batches:
Cooked batches no longer store index entries. Creation of indexes has
been delegated to commit callback.
2024-07-24 10:32:06 +02:00
Ivan Dyachkov 606d829256 Merge remote-tracking branch 'upstream/release-57' into 20240724-sync-release-57 2024-07-24 10:28:00 +02:00
zhongwencool c7a7658c7a
Merge pull request #13449 from zhongwencool/resource-log
feat: add group/type to resource slog
2024-07-24 14:34:25 +08:00
zhongwencool 4d7535df2d chore: use pgsqsl replace postgresql 2024-07-24 13:49:31 +08:00
lafirest 8a344a8646
Merge pull request #13504 from lafirest/feat/scram-http
feat(authn): added a HTTP backend for the authentication mechanism scram
2024-07-24 10:28:57 +08:00
Thales Macedo Garitezi 7374123c5c fix(jwt): fix grace period for renewal check 2024-07-23 17:25:29 -03:00
Thales Macedo Garitezi 9c0f1df8a3
Merge pull request #13506 from thalesmg/20240722-m-peername-sys-events
feat: add `peername` to rule events that already have `peerhost`
2024-07-23 09:38:57 -03:00
zhongwencool e7d07ea17c feat: add resource_type to emqx_resource behaviour 2024-07-23 18:24:28 +08:00
firest 7bf270a242 chore: update changes 2024-07-23 16:08:03 +08:00
firest 878b218692 feat(authn): added a HTTP backend for the authentication mechanism scram 2024-07-23 16:07:32 +08:00
zhongwencool e74a921d33 chore: compile error 2024-07-23 15:14:42 +08:00
zhongwencool 2a58a36e37 chore: add resource tag for log 2024-07-23 15:14:42 +08:00
zhongwencool 2bb062d3a3 chore: create_local/5 for emqx_resource_proto_v1 2024-07-23 15:14:42 +08:00
zhongwencool f29988ed8e chore: add tag to resouce log 2024-07-23 15:14:42 +08:00
zhongwencool e148d903e8 feat: log resource_id 2024-07-23 15:14:42 +08:00
zhongwencool 0a04b1ad6e feat: add group/type to resource slog 2024-07-23 15:14:41 +08:00
zhongwencool cba3f532f8 feat: don't record dry_run log 2024-07-23 15:14:41 +08:00
Xinyu Liu 7bb7b10a31
Merge pull request #13114 from emqx/emqx-relup-gen
feat: generate relup tarball, add relup APIs
2024-07-23 15:00:52 +08:00
Shawn 439abe430b refactor: remove relup revert callback functions 2024-07-23 11:45:55 +08:00
Shawn eb71477f43 chore: move relup_info to rel/relup 2024-07-23 09:32:54 +08:00
Thales Macedo Garitezi 99e6613713 test(rule events): add test cases for `schema.validation_failed` and `message.transformation_failed` events 2024-07-22 16:31:48 -03:00
Thales Macedo Garitezi d9832252d8 refactor: add namespace to avoid clashes with operations or other resources 2024-07-22 16:04:19 -03:00
Thales Macedo Garitezi 6a5849488c feat(cluster link): add metrics
Fixes https://emqx.atlassian.net/browse/EMQX-12627
2024-07-22 16:04:19 -03:00
Thales Macedo Garitezi 07cb147d38 fix(cluster link schema): username is not required 2024-07-22 16:04:19 -03:00
Thales Macedo Garitezi ba3cbe02e3 feat(cluster link api): add status to responses
Fixes https://emqx.atlassian.net/browse/EMQX-12627
2024-07-22 16:04:19 -03:00
Thales Macedo Garitezi 0b1f0db73c chore(cluster link): refactor HTTP API for CRUD operations
Fixes https://emqx.atlassian.net/browse/EMQX-12627
2024-07-22 16:04:19 -03:00
Thales Macedo Garitezi 7ca5205f3f feat: add `peername` to rule events that already have `peerhost`
Fixes https://emqx.atlassian.net/browse/EMQX-12342
2024-07-22 16:01:30 -03:00
Ivan Dyachkov d1c218303d
Merge pull request #13498 from emqx/sync-release-57-20240722-022026
Sync release-57
2024-07-22 19:30:10 +02:00
Thales Macedo Garitezi d7112921a6 docs: remove `enable` from config examples
Fixes https://emqx.atlassian.net/browse/EMQX-12730
2024-07-22 13:26:53 -03:00
Thales Macedo Garitezi 69f5b6fa6c chore: hide `enable` fields from docgen
Fixes https://emqx.atlassian.net/browse/EMQX-12730
2024-07-22 13:26:53 -03:00
Thales Macedo Garitezi 8ae54ac325 fix(connector resource): use configuration `resource_opts` for health check interval when starting up
Fixes https://emqx.atlassian.net/browse/EMQX-12738
2024-07-22 11:34:10 -03:00
Thales Macedo Garitezi 220fbe8a0a test: fix flaky test 2024-07-22 09:44:51 -03:00
zhongwencool a2bed1efb8
Merge pull request #13480 from zhongwencool/rule-engine-log-tag
feat: Rule engine log tag
2024-07-22 16:47:13 +08:00
zhongwencool 57b67ebb37
Merge pull request #13481 from zhongwencool/match_rule_error
chore: add authz tag to match_rule_error log
2024-07-22 16:46:49 +08:00
Shawn 862336a2cb feat: hide relup plugins from APIs and CLIs 2024-07-22 16:07:50 +08:00
id ed2fab51e9 Merge remote-tracking branch 'origin/release-57' into sync-release-57-20240722-022026 2024-07-22 02:20:27 +00:00
Thales Macedo Garitezi 65544f34ec chore: bump hocon -> 0.43.2 2024-07-19 17:25:18 -03:00
Thales Macedo Garitezi 8d535bbd24
Merge pull request #13464 from thalesmg/20240712-m-res-manager-shutdown-logs
chore: attempt to reduce race condition supervisor noproc shutdown error logs
2024-07-19 14:57:56 -03:00
Thales Macedo Garitezi d7e72808a8 docs: add changelog 2024-07-19 14:43:55 -03:00
Thales Macedo Garitezi 4d174b8678 feat(sources & actions api): add dependent rules to response
Fixes https://emqx.atlassian.net/browse/EMQX-12654
2024-07-19 14:43:55 -03:00
Thales Macedo Garitezi b5231c29e3 feat(bin/emqx): add `-init_debug` system arg when `DEBUG=2` 2024-07-19 12:32:37 -03:00
Thales Macedo Garitezi eb2d3a3b7e chore: attempt to reduce race condition supervisor shutdown errors
Fixes https://emqx.atlassian.net/browse/EMQX-12442

e.g.:
```
2024-05-23T08:52:39.811845+00:00 [error] Supervisor: {local,emqx_resource_manager_sup}. Context: shutdown_error. Reason: noproc. Offender: id=<<99, 101, 110, 115, 111, 114, 101, 100>>,pid=<0.7752.1030>.
```

It could be just a race condition, as it seems to be the case for resource manager: i) a call is made to the process to stop it; ii) the call times out; iii) the after clause ends up calling supervisor:terminate_child; iv) while the supervisor is finding the child to terminate, the process actually finishes terminating, and the supervisor receives a noproc reason back.
2024-07-19 10:57:00 -03:00
Thales Macedo Garitezi ae828e8cfb feat(connectors api): add dependent actions and sources to response
Fixes https://emqx.atlassian.net/browse/EMQX-12654
2024-07-19 10:33:48 -03:00
Thales Macedo Garitezi 464e202742
Merge pull request #13488 from thalesmg/20240718-m-mix-fix-machine-dep
chore(new mix build): fix app dependency for release
2024-07-19 09:21:02 -03:00
Andrew Mayorov b7200656a5
Merge pull request #13486 from keynslug/fix/ci/ds-raft-flaky-next
test(dsraft): attempt to stabilize flaky testcases
2024-07-19 12:15:36 +02:00
Shawn fc3405fe4c fix: bp_api for relup 2024-07-19 17:35:36 +08:00
Shawn f11dfce292 ci: suppress dialyzer checks for quicer and odbc types 2024-07-19 17:11:49 +08:00
Shawn c61828460a chore: emqx_utils_api:with_node/2 support simple http-code 2024-07-19 15:02:14 +08:00
Shawn 4d25f28bb2 fix: dialyzer checks 2024-07-19 14:19:50 +08:00
Shawn 5c2a7dfdfa fix: rename relup dir to relup_info to avoid tgz failure 2024-07-19 12:17:12 +08:00
Shawn 3ad7dc262b fix: some sanity-checks 2024-07-19 11:38:44 +08:00
Shawn 3c8ef35b18 fix: show relup status even if no packages installed 2024-07-19 11:20:37 +08:00
Thales Macedo Garitezi 01883e9759 chore(new mix build): fix app dependency for release 2024-07-18 11:33:02 -03:00
Thales Macedo Garitezi ca47e4768d
Merge pull request #13485 from thalesmg/20240717-r57-rm-dead-code-purge-proto
chore: remove dead code
2024-07-18 09:22:27 -03:00
Shawn 79b65a28c1 chore: use emqx-relup 0.1.0 2024-07-18 18:54:10 +08:00
Andrew Mayorov 3a893626b8
Merge pull request #13474 from keynslug/ft/EMQX-12309/ds-cas-api
feat(ds): allow isolated batches with preconditions
2024-07-18 12:52:13 +02:00
Shawn 2008130071 feat: add HTTP APIs for relup 2024-07-18 18:48:38 +08:00
Shawn c6b02bc13f feat: support starting emqx from relup dir
We put all of the unpacked files into `relup` dir, and warn the user if boot from it
2024-07-18 18:47:27 +08:00
Ivan Dyachkov 4a04ffdca1
Merge pull request #13483 from id/20240717-sync-release-57
sync release-57
2024-07-18 10:41:49 +02:00
Ivan Dyachkov c2d49ff34f chore(rmq_tests): fix rabbitmq tests
Co-authored-by: Ilya Averyanov <av@rubybox.dev>
2024-07-18 08:34:00 +02:00
zhongwencool ac52bf39ce
Merge pull request #13443 from zhongwencool/cluster-link-cli-load
fix: update cluster.links via cli
2024-07-18 09:13:59 +08:00
Andrew Mayorov 0e545ffcec
feat(ds): add dedicated `#message_matcher{}` for preconditions 2024-07-17 21:27:17 +02:00
Andrew Mayorov 2e89656a90
test(dsraft): start `t_replication_transfers_snapshots` from stable state 2024-07-17 20:01:55 +02:00
Andrew Mayorov 466fa41ec3
fix(dsraft): rely on last resort timeout with unresponsive replicas
This simplifies the shard transition scheduling logic and makes it less
prone to races.
2024-07-17 19:24:38 +02:00
Thales Macedo Garitezi 93c725732c chore: remove dead code 2024-07-17 12:56:45 -03:00
Thales Macedo Garitezi 4edbcc55e7
Merge pull request #13463 from thalesmg/20240712-m-gprodu-backoff-retry
feat(gcp pubsub producer): retry on 502 and 503 http status code responses
2024-07-17 12:49:27 -03:00
Thales Macedo Garitezi cd8bf2725a
Merge pull request #13453 from thalesmg/20240711-r57-mt-fixes
batch of message transformation fixes
2024-07-17 12:45:19 -03:00
Andrew Mayorov 0c05b3f019
fix(ds): make conditionals less confusing 2024-07-17 16:23:41 +02:00
Andrew Mayorov 78fe9304be
Merge pull request #13462 from keynslug/fix/ci/flaky-ds-raft
fix(dsraft): preserve pending replica set transitions
2024-07-17 16:11:59 +02:00
Andrew Mayorov 14022aded1
feat(ds): allow isolated batches with preconditions
Namely, single message deletions and preconditions that can be used to
build complex "compare-and-swap"-style operations. Also allow user to
declare that atomic batches support is needed for a DB.
2024-07-17 15:57:17 +02:00
Andrew Mayorov 02e1007a16
feat(dslocal): implement `force_monotonic_timestamps => false` 2024-07-17 15:49:50 +02:00
zhongwencool 3381eecd6f chore: apply code review 2024-07-17 21:27:07 +08:00
zhongwencool 3c832db13d test: test cluster.links reloaded 2024-07-17 21:06:48 +08:00
zhongwencool 937fb153c2 fix: fill_default/3 should populate default values for all parameters except the 'ds' 2024-07-17 21:06:48 +08:00
zhongwencool 7b6b9580c8 test: add test for updating cluster.links 2024-07-17 21:06:48 +08:00
zhongwencool 2783192f77 fix: update cluster.links via cli 2024-07-17 21:06:48 +08:00
zhongwencool 083537daa3 fix: retry not_found if conf file not exist 2024-07-17 21:06:48 +08:00
Andrew Mayorov ae3812da85
feat(ds): allow to turn monotonic timestamps off for DB
That tells implementation how to assign timestamps to messages. Current
implicit default is now `force_monotonic_timestamps => true`.
2024-07-17 14:40:23 +02:00
zmstone 4c51cfdb68
Merge pull request #13445 from tigercl/docs/improve-desc
docs: improve the desc of configuration items
2024-07-17 14:37:12 +02:00
Andrew Mayorov 6b130c6422
fix(dsraft): preserve pending replica set transitions
Otherwise, information about pending replica set transitions taking a
long time to complete could be lost on subsequent target set changes and
node crashes.
2024-07-17 12:17:07 +02:00
zhouzb 67880ab6a0 docs: improve the desc of configuration items
docs: fix typos

docs: better line breaks

docs: improve desc

docs: fix typo

docs: update desc for shared_subscription_strategy_enum

docs: fix typo

docs: update desc

docs: fix typo
2024-07-17 17:39:36 +08:00
Ivan Dyachkov 292b331064 Merge remote-tracking branch 'upstream/release-57' into 20240717-sync-release-57 2024-07-17 11:29:25 +02:00
zhongwencool 52031441cf chore: add authz tag to match_rule_error log 2024-07-17 12:21:32 +08:00
zhongwencool 604cff4887 feat: add rule tag to rule_engine log 2024-07-17 12:15:57 +08:00
lafirest 6697035812
Merge pull request #13441 from lafirest/feat/coap
feat(coap): use content-sensitive udp proxy for coap
2024-07-17 10:01:51 +08:00
Thales Macedo Garitezi 1ad02a11e2
Merge pull request #13455 from thalesmg/20240711-m-mix-umbrella-part-III-no-ci
sync new mix build work to master
2024-07-16 14:41:10 -03:00
Andrew Mayorov d04915d6a6
test(dsraft): increase `ra_server` logging level for debugging 2024-07-16 15:54:49 +02:00
Andrew Mayorov 78bb102311
test(dsraft): attempt to start select testcases from stable state 2024-07-16 15:54:49 +02:00
ieQu1 706cab3c86
Merge pull request #13467 from ieQu1/dev/optimize-connection-process_msg
fix(connection): Make process_msg function tail-recursive
2024-07-15 17:00:50 +02:00
Thales Macedo Garitezi 4a08bfc93f feat(mix ct): improve failure logging 2024-07-15 09:26:04 -03:00
Thales Macedo Garitezi 0555a8ec61 fix(mix): bizarre compilation order bug with `emqx` profile
For some bizarre reason, if the `:apps` key is defined in the `project()` callback in the
root umbrella `mix.exs`, it messes up the compilation order that mix follows when
compiling the project from scratch.

Specifically, in the `emqx` profile, even though `:emqx_utils` is an explicit dependency
of `:emqx_ds_builtin_local`, mix insisted in compiling the latter before the former, and
failing, obviously.  Removing the explicit `:apps` from the project definition solved
this.

🫠
2024-07-15 09:26:04 -03:00
Thales Macedo Garitezi 02a0ccfdd1 ci: preparations for new mix build 2024-07-15 09:26:04 -03:00
Thales Macedo Garitezi 9a003ee3cf feat(mix eunit): add support for filtering test cases 2024-07-15 09:26:04 -03:00
Thales Macedo Garitezi bbd51bdf18 feat(mix ct): add support for specifying group paths 2024-07-15 09:26:04 -03:00
Thales Macedo Garitezi 39c82fbe89 feat(mix): always run merge-config before release 2024-07-15 09:26:04 -03:00
Thales Macedo Garitezi 70786d6aca test: fix suite apps 2024-07-15 09:26:04 -03:00
Thales Macedo Garitezi 066fd0481b feat(mix): compile asn1 files 2024-07-15 09:26:04 -03:00
Thales Macedo Garitezi 9e4a84cf76
Merge pull request #13442 from thalesmg/20240709-r57-decouple-connector-action-hc
fix(resource manager): disentangle connector and channel health check frequencies
2024-07-15 09:12:07 -03:00
firest 269f6b29cc chore: update changes 2024-07-15 11:26:55 +08:00
firest ec183f1d4c test(coap): fix ci errors 2024-07-15 10:52:37 +08:00
ieQu1 46c2c75b7b
fix(connection): Make process_msg function tail-recursive 2024-07-14 06:00:00 +02:00
Thales Macedo Garitezi 0e57b39cf2 feat(gcp pubsub producer): retry on 502 and 503 http status code responses
Fixes https://emqx.atlassian.net/browse/EMQX-12625
2024-07-12 15:29:59 -03:00
Andrew Mayorov 2401a2fb80
test(dsraft): run `t_join_leave_errors` case in tracing context 2024-07-12 18:28:24 +02:00
Thales Macedo Garitezi 96c9020727 chore: improve protobuf decoding error messages
Fixes https://emqx.atlassian.net/browse/EMQX-12677
2024-07-12 13:27:30 -03:00
Andrew Mayorov af81800aec
chore(dsraft): log a bit more informative messages in shard allocator 2024-07-12 18:24:58 +02:00
Andrew Mayorov 8e8b382ec0
chore(dsraft): provide more details when replica is unready 2024-07-12 18:23:23 +02:00
Andrew Mayorov 70a760850f
chore(dsraft): correct comment spelling errors 2024-07-12 15:27:29 +02:00
Andrew Mayorov 205ad507ea
test(dsraft): attempt to ensure testcases start from stable state
Where "stable state" is currently defined as "everyone knows and agrees
on the current leader".
2024-07-12 15:26:00 +02:00
Ivan Dyachkov ffa69df6f8
Merge pull request #13461 from id/20240712-ci-add-sync-release-branch-workflow
ci: add sync-release-branch workflow
2024-07-12 13:13:00 +02:00
Ivan Dyachkov e07d96e4d8 ci: add sync-release-branch workflow 2024-07-12 12:52:16 +02:00
Ilia Averianov 82e723bd18
Merge pull request #13459 from savonarola/0712-reduce-flackyness
chore(mgmt): reduce test flakyness
2024-07-12 13:14:14 +03:00
Ilya Averyanov 9ca8aeb155 chore(mgmt): reduce test flakyness 2024-07-12 12:10:49 +03:00
firest 854754eb60 feat(coap): use content-sensitive udp proxy for coap 2024-07-12 16:23:46 +08:00
lafirest 4e3095b1c4
Merge pull request #13458 from lafirest/fix/banned_bf
fix(banned): let the bootfile of banned be optional
2024-07-12 15:00:43 +08:00
firest 83cc3ffeb0 fix(banned): let the bootfile of banned be optional 2024-07-12 13:58:14 +08:00
lafirest 1b7d23cef4
Merge pull request #13451 from lafirest/fix/def_banned_file
fix: do not convert a empty file name to a empty list
2024-07-12 13:50:32 +08:00
Thales Macedo Garitezi 2816170e9d chore: add `$events.message_transformation_failed` to rule engine tester
Fixes https://emqx.atlassian.net/browse/EMQX-12679
2024-07-11 17:52:08 -03:00
Thales Macedo Garitezi 5f595966d8 chore(message transformation): allow empty operation list
Fixes https://emqx.atlassian.net/browse/EMQX-12682
2024-07-11 17:52:08 -03:00
Thales Macedo Garitezi 5be654e31e
Merge pull request #13456 from thalesmg/20240711-r57-minor-schema-registry-api-nit
fix(schema registry): handle large names during lookup
2024-07-11 17:50:58 -03:00
Thales Macedo Garitezi 04b547d6f5 fix(schema registry): handle large names during lookup
Fixes https://emqx.atlassian.net/browse/EMQX-12692
2024-07-11 14:35:31 -03:00
Thales Macedo Garitezi 21313c766d ci: add dialyzer mix task 2024-07-11 14:19:23 -03:00
Thales Macedo Garitezi f3c6d10f76 fix(mix): fix compile paths and deps 2024-07-11 14:19:23 -03:00
Thales Macedo Garitezi 01d89be743 feat(message transformation): add timestamp and pub_props fields to read context
Fixes https://emqx.atlassian.net/browse/EMQX-12684

Fixes https://emqx.atlassian.net/browse/EMQX-12678
2024-07-11 12:15:31 -03:00
Thales Macedo Garitezi 44e4b3616d feat(variform): allow hyphens in identifiers
Fixes https://emqx.atlassian.net/browse/EMQX-12683
2024-07-11 12:15:23 -03:00
Kjell Winblad a4cc3ba9e8
Merge pull request #13375 from kjellwinblad/kjell/fix_connector_lister_speed_limit_clearing/EMQX-12514
fix: default value for max_conn_rate etc should be set to infinity
2024-07-11 16:36:01 +02:00
Ivan Dyachkov bf2abba17a
Merge pull request #13448 from id/20240711-fix-dashboard-tests-again
ci: fix dashboard tests (again)
2024-07-11 12:36:25 +02:00
firest d9b5c5863b fix: do not convert a empty file name to a empty list 2024-07-11 18:12:38 +08:00
lafirest c9e12f30cd
Merge pull request #13444 from lafirest/fix/oidc
fix(oidc): Avoid crashes and avoid deleting jwks on update
2024-07-11 17:55:50 +08:00
Ivan Dyachkov 3004e32473 ci: fix dashboard tests (again) 2024-07-11 11:29:29 +02:00
zmstone 7664b06e98
Merge pull request #13434 from zmstone/0704-refine-rpc-config
0704 refine rpc config
2024-07-11 10:25:45 +02:00
ieQu1 02ce7e1b07
Merge pull request #13446 from ieQu1/dev/ds-build-platform
chore(ds): Support platform profile
2024-07-10 13:26:01 +02:00
ieQu1 4825079964
chore(ds): Support platform profile 2024-07-10 12:03:23 +02:00
firest b0e3e405cf fix(oidc): Avoid crashes and avoid deleting jwks on update 2024-07-10 15:22:43 +08:00
JimMoen 44d533fe6d
Merge pull request #13432 from JimMoen/0705-fix-jwt-pem-check
fix: create authn jwt with bad public key
2024-07-10 10:33:54 +08:00
zmstone 917df38a07 docs: add changelog for PR 13434 2024-07-09 22:26:30 +02:00
zmstone 7a23ae7b4d refactor: expose only server_port for rpc
previously, there were 4 port configs:
- tcp_server_port
- ssl_server_port
- tcp_client_port
- ssl_client_port
2024-07-09 22:26:29 +02:00
zmstone ee13773496 refactor: rename rpc.tcp_client_num to rpc.client_num
tcp_client_num is kept as an alias
2024-07-09 22:26:29 +02:00
Thales Macedo Garitezi 48e604bda8 fix(mix grpc): include default erlc options 2024-07-09 15:56:30 -03:00
Thales Macedo Garitezi 818070ad44 test(mix): add integration test path 2024-07-09 15:56:30 -03:00
Thales Macedo Garitezi 5279ad76be fix(grpc compiler): unload apps to avoid side effects 2024-07-09 15:56:30 -03:00
Thales Macedo Garitezi b91515b131 fix(schema registry mix): gpb is a runtime dep 2024-07-09 15:56:30 -03:00
Thales Macedo Garitezi 6d94809950
Merge pull request #13415 from thalesmg/20240703-m-couchbase-action
feat: implement couchbase connector and action
2024-07-09 15:53:11 -03:00
Thales Macedo Garitezi 50e6ee4c88
Merge pull request #13435 from thalesmg/20240708-r57-mt-breaking-changelog
docs: add breaking change entry
2024-07-09 15:53:02 -03:00
Thales Macedo Garitezi 3c370a90aa
Merge pull request #13436 from thalesmg/20240708-r57-custom-headers-jwks
feat(jwks): allow specifying custom request headers
2024-07-09 15:52:44 -03:00
ieQu1 92dc059908
Merge pull request #13370 from ieQu1/dev/skip-streams
New durable storage layout with explicit index for LTS wildcards
2024-07-09 20:27:21 +02:00
Thales Macedo Garitezi 9f8a1885a7 fix(resource manager): disentangle connector and channel health check frequencies
Fixes https://emqx.atlassian.net/browse/EMQX-12674
2024-07-09 14:53:39 -03:00
Thales Macedo Garitezi d25c4ba06f
Merge pull request #13421 from thalesmg/20240705-r57-docs-mt-api-examples
docs(message transformation): add api examples
2024-07-09 10:16:53 -03:00
ieQu1 3721be65ee
fix(ds): Improve comments 2024-07-09 13:15:15 +02:00
ieQu1 d7732a6aac
test(ds): Attempt to stabilize a flaky test 2024-07-09 13:15:15 +02:00
ieQu1 e70c1cfea3
test(ds): Improve stability of replication test suite 2024-07-09 13:15:15 +02:00
ieQu1 dc4ae82798
test(ds): Add message ID 2024-07-09 13:15:14 +02:00
ieQu1 d1b574a67e
perf(dslocal): Run heavy-duty operations in a temporary process 2024-07-09 13:15:14 +02:00
ieQu1 661f79544b
fix(ds): Optimize hot loop of skipstream storage layout 2024-07-09 13:15:14 +02:00
ieQu1 23dafbb03b
feat(ds): Add a benchmarking tool for storage efficiency analysis 2024-07-09 13:15:14 +02:00
ieQu1 afeb2ab8aa
feat(ds): Add metrics for skipstream layout 2024-07-09 13:15:14 +02:00
ieQu1 b68ebb9a73
test(dsrepl): Generalize tests to use different storage layouts 2024-07-09 13:15:14 +02:00
ieQu1 8c5e4a2376
test(ds): Generalize storage layout test suite for different layouts 2024-07-09 13:15:14 +02:00
ieQu1 086e7256f5
feat(ds): Add configuration schema for skipstream LTS layout 2024-07-09 13:15:14 +02:00
ieQu1 a4642d4d06
feat(ds): Add a new storage layout engine: "skipstream"
This layout is based on LTS as well, but it uses separate index
streams for constrained replay of streams with learned wildcards
2024-07-09 13:15:14 +02:00
ieQu1 de48077ac4
test(ds): Add new helper functions
- Improve message comparison
- Add set operations
2024-07-09 13:15:14 +02:00
ieQu1 210556e545
feat(ds): Generalize value serialization
- Add a new utility module for message serialization
- Add experimental serializer based on ASN.1
2024-07-09 13:15:14 +02:00
ieQu1 843973ef32
fix(ds): bitfield_lts: static_key_size -> static_key_bits 2024-07-09 13:15:14 +02:00
ieQu1 f84fb34692
feat(ds_lts): New APIs: info, reverse lookups and topic compression 2024-07-09 13:15:14 +02:00
ieQu1 eb80402ccb
fix(ds): Improve typespecs and descriptions in storage_layer 2024-07-09 13:15:14 +02:00
ieQu1 71dad0242e
docs(ds): Move Raft-related parts to emqx_ds_builtin_raft README 2024-07-09 13:15:14 +02:00
ieQu1 afe1c5617d
refactor(ds): Rename macros for bitfield_lts metrics 2024-07-09 13:15:14 +02:00
ieQu1 0f2c19b656
refactor(ds): Move end_of_stream detection logic for delete_next 2024-07-09 13:15:14 +02:00
ieQu1 b565976794
fix(ds): Fix hashing of empty wildcard topic levels in bitfield_lts 2024-07-09 13:15:13 +02:00
zmstone 91fd01ed21
Merge pull request #13411 from Altair-Bueno/master
new(helm): websocket ingress (fixes #13309)
2024-07-09 11:39:07 +02:00
Thales Macedo Garitezi 0d1eaba82e
Merge pull request #13437 from thalesmg/20240708-m-fix-includes
fix(ds builtin local): use `-include_lib` instead of relative path
2024-07-08 18:40:11 -03:00
Thales Macedo Garitezi f00bb383d4 fix(ds builtin local): use `-include_lib` instead of relative path 2024-07-08 16:57:55 -03:00
Thales Macedo Garitezi 811184ddad feat(jwks): allow specifying custom request headers
Fixes https://emqx.atlassian.net/browse/EMQX-12655
2024-07-08 15:40:52 -03:00
Thales Macedo Garitezi 893630aee3 docs: add breaking change entry
Fixes https://github.com/emqx/emqx/pull/13420#issuecomment-2213957235
2024-07-08 10:18:12 -03:00
Thales Macedo Garitezi d34fc7a03a
Merge pull request #13420 from thalesmg/20240705-r57-fix-mt-empty-topics
fix(schema validation & message transformation): forbid empty topic filter list
2024-07-08 10:15:08 -03:00
Thales Macedo Garitezi 166f5e5f12
Merge pull request #13426 from thalesmg/20240705-r57-test-flaky-plugin-start-enabled
test(plugins): fix flaky test
2024-07-08 09:19:53 -03:00
zhongwencool fd18e5feb3
Merge pull request #13202 from zhongwencool/cluster-fix-cli
feat: add cluster fix command
2024-07-08 19:08:34 +08:00
zhongwencool 820789a09f fix: redact status when mark_fix_log begin 2024-07-08 17:32:45 +08:00
zhongwencool 457ea93570 test: add cluster_sync cli test 2024-07-08 17:04:41 +08:00
zhongwencool f490a0cba2 feat: don't reset tnx_id when cluster_fix 2024-07-08 17:04:41 +08:00
zhongwencool 298211d101 chore: apply suggestions from code review
Co-authored-by: zmstone <zmstone@gmail.com>
2024-07-08 17:04:41 +08:00
zhongwencool bdf3fc63a6 chore: add config leader to suggestion 2024-07-08 17:04:41 +08:00
zhongwencool 22fc3c49cc chore: combine some common code into one function 2024-07-08 17:04:41 +08:00
zhongwencool 5b105fcdbb chore: move emqx_conf_proto_v3 to emqx_conf_proto_v4 2024-07-08 17:04:41 +08:00
zhongwencool 3ed4340145 test: fix cluster_rpc test failed 2024-07-08 17:04:41 +08:00
zhongwencool 2069910ad1 feat: add cluster fix command 2024-07-08 17:04:41 +08:00
JimMoen ae3b8fe146
test: create jwt authenticator with bad public key 2024-07-08 16:52:18 +08:00
JimMoen f76444fbf8
fix: create authn jwt with bad public key 2024-07-08 16:52:18 +08:00
Shawn 5fca0a16f9 feat: rename emqx_relup to emqx_post_upgrade 2024-07-08 10:33:09 +08:00
Shawn 92594d042b feat: add some relup examples 2024-07-08 10:33:09 +08:00
Shawn e9163f2752 feat: generate relup tarball
To generate a tarball, tag the release and then:

```
make emqx-enterprise-relup
```
2024-07-08 10:33:09 +08:00
zhongwencool 29d7a511f1
Merge pull request #13419 from zhongwencool/port-pr
Port: some minor bug fixes from master
2024-07-06 14:42:51 +08:00
Thales Macedo Garitezi f9b6ae0c1a
Merge pull request #13422 from thalesmg/20240705-r57-max-heap-size-0
fix: handle `max_heap_size` = 0
2024-07-05 15:58:06 -03:00
Thales Macedo Garitezi f1b4467fe1 test(plugins): fix flaky test
Hypothesis is that both peer nodes were using the same directory and stepping on each
other's toes.
2024-07-05 14:17:42 -03:00
Thales Macedo Garitezi 70fab51354 fix: handle `max_heap_size` = 0
Fixes https://github.com/emqx/emqx/issues/13417

Fixes https://emqx.atlassian.net/browse/EMQX-12659
2024-07-05 13:10:37 -03:00
Kjell Winblad c8258cebe8
Merge pull request #13414 from kjellwinblad/kjell/review_connector_error_logs_rabbitmq_etc/EMQX-12462
fix: make RabbitMQ error log messages easier to understand
2024-07-05 15:01:15 +02:00
Thales Macedo Garitezi 36ee7bed77 docs(message transformation): add api examples
Fixes https://emqx.atlassian.net/browse/EMQX-12645
2024-07-05 09:59:27 -03:00
Thales Macedo Garitezi e7351d949d fix(schema validation): forbid empty topic filter list 2024-07-05 09:51:43 -03:00
Thales Macedo Garitezi e99fee68c0 fix(message transformation): forbid empty topic filter list
Fixes https://emqx.atlassian.net/browse/EMQX-12646
2024-07-05 09:49:03 -03:00
zhongwencool 7d851872ec chore: update emqx_module's app version 2024-07-05 19:21:28 +08:00
zhongwencool 9ffe6420c2 chore: add changelog for 13419 2024-07-05 17:41:02 +08:00
zhongwencool d94fcb9cfd test: fix api_config SUITE failed 2024-07-05 17:34:39 +08:00
zhongwencool ba3097dc56 fix: observer command crash when can't find object code 2024-07-05 17:34:33 +08:00
zhongwencool f0a1d785ca fix: don't allow set active_n to negative int 2024-07-05 17:34:25 +08:00
zhongwencool 8aab919f74 fix: load bad configs return unknown msg 2024-07-05 17:34:17 +08:00
zhongwencool b4cffc581b fix: ws/wss's max_frame_size should > 0 2024-07-05 17:34:09 +08:00
Kjell Winblad aeacb3d58a docs: add change log entry 2024-07-05 11:05:21 +02:00
JimMoen c7f4e85760
Merge pull request #13418 from JimMoen/fix-docker-build-warning
build: avoid warnings during docker build
2024-07-05 17:03:14 +08:00
Altair-Bueno f2f8c2ae92 fix(helm): Default to /mqtt on ingress as Rory-Z suggestion 2024-07-05 09:09:30 +02:00
JimMoen 3e69a52596
build: avoid warnings during docker build
- See also: https://docs.docker.com/reference/build-checks/from-as-casing/
2024-07-05 14:06:58 +08:00
zhongwencool 094259f444
Merge pull request #13408 from zhongwencool/password-crash
chore: improve auth error for invalid salt/password type
2024-07-05 11:44:21 +08:00
zhongwencool 755d6c9e0f chore: add changelog for 13398 and 13408 2024-07-05 10:21:04 +08:00
JimMoen 9d0b5a9bc6
Merge pull request #13412 from JimMoen/fix-cert-notafter-badmatch
fix: obtain cert expiry epoch failed due to formated `generalTime`
2024-07-05 10:13:22 +08:00
zhongwencool d3d3303dcb chore: improve auth error for invalid salt/password type 2024-07-05 10:12:24 +08:00
lafirest aa84ca5a88
Merge pull request #13386 from lafirest/feat/banned_boot_57
feat(banned): add a bootstrap file for banned
2024-07-05 08:47:40 +08:00
Thales Macedo Garitezi c4dd167cb9 feat: implement couchbase connector and action
Fixes https://emqx.atlassian.net/browse/EMQX-12545
2024-07-04 17:51:59 -03:00
Thales Macedo Garitezi b333babb4c
Merge pull request #13401 from thalesmg/20240703-r57-authz-ignore-api-metrics
fix(authz api): add new `ignore` metric to status response
2024-07-04 17:07:08 -03:00
JimMoen d84d31cbc5
test: cert expiry epoch with `generalTime` formatted 2024-07-05 01:47:13 +08:00
Thales Macedo Garitezi 16113001fe
Merge pull request #13413 from thalesmg/20240703-m-mix-umbrella-part-II
chore: add missing mix files to new apps
2024-07-04 14:27:59 -03:00
Kjell Winblad b994e0f1c0 fix: make RabbitMQ error log messages easier to understand
Fixes:
https://emqx.atlassian.net/browse/EMQX-12462
2024-07-04 16:43:53 +02:00
Thales Macedo Garitezi 420493deb4 chore: add missing mix files to new apps 2024-07-04 10:27:59 -03:00
Kjell Winblad d206d24975 fix: only set default for max_conn_rate and update test case
This revert the change in commit e291dcd for all listener "short
path fields" except the field max_conn_rate so they no longer have a
default value. It also updates a test case that assume that no listener
config is created by default but this is no longer the case when there
is a default value for the max_conn_rate field.
2024-07-04 14:32:10 +02:00
Thales Macedo Garitezi f758fd9279
Merge pull request #13405 from thalesmg/20240703-r57-test-flaky-table-removed-postgres
test(postgres bridge): attempt to stabilize flaky test
2024-07-04 09:25:15 -03:00
JimMoen 8c6cd69caa
fix: obtain cert expiry epoch failed due to formated `generalTime` 2024-07-04 18:23:56 +08:00
Altair-Bueno 20be0df62d feat(helm): websocket ingress
Closes: #13309
2024-07-04 10:52:42 +02:00
zhongwencool ac77b8a131
Merge pull request #13403 from zmstone/0703-upgrade-hocon-0.43.1
0703 upgrade hocon 0.43.1
2024-07-04 09:30:48 +08:00
firest a912751458 chore: update changes 2024-07-04 09:13:50 +08:00
firest 913e0ce18b feat(banned): add a bootstrap file for banned 2024-07-04 09:12:12 +08:00
zmstone 947cddb2eb test: invalid map key is caught by hocon
now that hocon has a built-in map key validation,
some of the resource name validations are cought by hocon
2024-07-03 23:00:18 +02:00
zmstone 5446bc305f docs: add changelog for PR 13403 2024-07-03 23:00:18 +02:00
zmstone eaaee725c2 fix: upgrade to hocon 0.43.1
included 3 changes since 0.42.2

- allow validation of map keys
- improve crash stacktrace report
- avoid dumping array environment variable values
2024-07-03 23:00:14 +02:00
Thales Macedo Garitezi e9265b88e5
Merge pull request #13406 from thalesmg/20240703-m-sync-r57
sync release-57 to master
2024-07-03 17:21:02 -03:00
zmstone 7ee5b90084
Merge pull request #13400 from zmstone/0605-ACL-rules-in-http-authentication-response
feat(auth): support HTTP authn return ACL rules
2024-07-03 21:51:07 +02:00
Thales Macedo Garitezi 32ace85e1c Merge branch 'release-57' into 20240703-m-sync-r57 2024-07-03 16:03:15 -03:00
Thales Macedo Garitezi ae24b7a37b
Merge pull request #13404 from thalesmg/20240703-r57-refactor-mix-common-deps
ci(mix): refactor to avoid conflicts
2024-07-03 15:57:05 -03:00
Thales Macedo Garitezi 72579f9014 test(postgres bridge): attempt to stabilize flaky test
```
%%% emqx_bridge_pgsql_SUITE ==> tcp.sync.with_batch.t_table_removed: FAILED
%%% emqx_bridge_pgsql_SUITE ==> {{panic,
     #{msg => "Unexpected result",
       result =>
           {run_stage_failed,exit,
               {test_case_failed,
                   "unexpected result: {error,{recoverable_error,sync_required}}"},
               [{emqx_bridge_pgsql_SUITE,'-t_table_removed/1-fun-3-',3,
                    [{file,
                         "/emqx/apps/emqx_bridge_pgsql/test/emqx_bridge_pgsql_SUITE.erl"},
                     {line,822}]},
```

```
Error: -03T17:52:54.046809+00:00 [error] Generic server <0.352770.0> terminating. Reason: {'module could not be loaded',[{undefined,handle_message,[90,<<"I">>,{state,ssl,{sslsocket,{gen_tcp,#Port<0.1671>,tls_connection,undefined},[<0.352774.0>,<0.352773.0>]},<<>>,{336,-2093820527},on_message,{codec,#{},[null,undefined],{oid_db,#{16 =>
...
2024-07-03T17:52:54.075446+00:00 [critical] Run stage failed: exit:{test_case_failed,"unexpected result: {error,\n                    {resource_error,\n                     #{reason => exception,\n                       msg =>\n                        #{error =>\n                           {exit,\n                            {{undef,\n                              [{undefined,handle_message,\n                                [90,<<\"I\">>,\n                                 {state,ssl,\n                                  {sslsocket,\n                                   {gen_tcp,#Port<0.1671>,tls_connection,\n
```
2024-07-03 15:05:00 -03:00
Thales Macedo Garitezi afb65817c4 ci(mix): refactor to avoid conflicts
This introduces a refactoring that will hopefully help avoid conflicts with ongoing work
to migrate our build / CI tooling to Mix.
2024-07-03 14:37:25 -03:00
Andrew Mayorov 187f5e5936
Merge pull request #13391 from keynslug/perf/EMQX-12611/avoid-stream-shuffle
perf(sessds): rotate through streams with iterators when fetching
2024-07-03 17:46:29 +02:00
Andrew Mayorov 45dbfb77e3
Merge pull request #13402 from keynslug/ci/flaky/s3-aggreg
test(bridge-s3): correct assertions to get rid of flakiness
2024-07-03 17:44:42 +02:00
Andrew Mayorov d7d5eb2c52
test(bridge-s3): correct assertions to get rid of flakiness 2024-07-03 16:40:34 +02:00
Thales Macedo Garitezi 532c7831b2
Merge pull request #13384 from thalesmg/20240701-r57-mt-new-fields
feat(message transformation): add more read-only fields to context
2024-07-03 11:27:27 -03:00
Thales Macedo Garitezi 35f1ddc0eb
Merge pull request #13393 from thalesmg/20240702-r57-test-plugin-start-enabled
fix(plugins): ensure plugin apps are restarted when restarting `emqx_plugins`
2024-07-03 11:27:14 -03:00
zmstone 9194756963 feat(auth): support HTTP authn return ACL rules 2024-07-03 15:37:11 +02:00
Andrew Mayorov 950f4d9483
fix(sessds): defend restartable stream iterator from infinite loop 2024-07-03 15:21:16 +02:00
Andrew Mayorov 947af1faaf
chore(sessds): rename `iterate` -> `iter_next` for consistency 2024-07-03 15:21:16 +02:00
Thales Macedo Garitezi c3579f338b fix(authz api): add new `ignore` metric to status response
Fixes https://emqx.atlassian.net/browse/EMQX-12411
2024-07-03 10:16:18 -03:00
Thales Macedo Garitezi e1420a27bb fix(plugins): ensure plugin apps are restarted when restarting `emqx_plugins`
Fixes https://emqx.atlassian.net/browse/EMQX-12628
Fixes https://github.com/emqx/emqx/issues/13378
2024-07-03 09:51:42 -03:00
Thales Macedo Garitezi 2c3209e258
Merge pull request #13395 from thalesmg/20240702-r57-test-flaky-cluster-invite-timeout
test: attempt to fix flaky tests
2024-07-03 09:32:58 -03:00
zhongwencool 17261c6499
Merge pull request #13379 from emqx/dependabot/github_actions/actions-b098ddba97
build(deps): bump the actions group across 1 directory with 3 updates
2024-07-03 17:28:05 +08:00
zhongwencool 7f17981a12
Merge pull request #13392 from thalesmg/20240702-m-sync-r57-mix-umbrella
sync release-57 to master
2024-07-03 16:24:24 +08:00
zhongwencool fe256363ad
Merge pull request #13331 from lafirest/fix/error-msg
fix(api_keys): improved the error message when bootstrapping api_key
2024-07-03 15:38:44 +08:00
zhongwencool cfa29eaa6f Merge remote-tracking branch 'upstream/release-57' into 20240702-m-sync-r57-mix-umbrella 2024-07-03 15:30:11 +08:00
zhongwencool 5f321702e7
Merge pull request #13398 from zhongwencool/authz-db-clear-table
fix: don't destory when authz'source unchanged
2024-07-03 15:29:39 +08:00
JianBo He 9f44c50025
Merge pull request #13350 from HJianBo/add-peersni-to-client-attr
feat: support to extract the client peersni field to clientinfo
2024-07-03 15:29:21 +08:00
zhongwencool cfa7c3bf04 Merge remote-tracking branch 'upstream/release-57' into 20240702-m-sync-r57-mix-umbrella 2024-07-03 15:15:58 +08:00
zhongwencool f4527ce609
Merge pull request #13371 from zhongwencool/update-config-not-failed-on-replicant
feat: do not fail on other nodes when the RPC succeeds on the first node
2024-07-03 15:00:00 +08:00
zhongwencool 112433da87 fix: don't destory when authz'source unchanged 2024-07-03 13:13:23 +08:00
firest ac6bbd2977 fix(api_keys): improved the error message when bootstrapping api_key 2024-07-03 11:08:47 +08:00
zhongwencool 0dfa3e8c86 chore: ensure the module is loaded 2024-07-03 10:11:33 +08:00
JianBo He 920e039487 chore: fix failed tests 2024-07-03 09:55:45 +08:00
zhongwencool 7c02e1979e chore: add cluster_rpc_opts() type in emqx_config 2024-07-03 09:49:14 +08:00
zhongwencool 059baf9ea5 test: add authz test case 2024-07-03 09:49:13 +08:00
zhongwencool e1c3b7587d feat: do not fail on other nodes when the RPC succeeds on the first node 2024-07-03 09:49:13 +08:00
Thales Macedo Garitezi 9ef3eff4c6
Merge pull request #13394 from thalesmg/20240702-r57-atom-leak-schema-registry
fix(schema registry): avoid atom leak
2024-07-02 17:40:26 -03:00
Thales Macedo Garitezi fdf43455d9
Merge pull request #13383 from thalesmg/20240701-r57-test-flaky-gconsu-multiple-pull-workers
test: attempts to stabilize flaky tests
2024-07-02 17:40:10 -03:00
Thales Macedo Garitezi b0c0c02df9 test: attempt to fix flaky tests
```
%%% emqx_mgmt_api_cluster_SUITE ==> t_cluster_invite_api_timeout: FAILED
%%% emqx_mgmt_api_cluster_SUITE ==>
Failure/Error: ?assertMatch([ # { core_node := Core1 , replicant_nodes := [ # { node := Replicant , streams := _ } ] } , # { core_node := Core2 , replicant_nodes := [ # { node := Replicant , streams := _ } ] } ], lists : sort ( Core1Resp ))
  expected: = [ # { core_node := Core1 , replicant_nodes := [ # { node := Replicant , streams := _ } ] } , # { core_node := Core2 , replicant_nodes := [ # { node := Replicant , streams := _ } ] } ]
       got: [#{core_node => 'data_backup_core1@127.0.0.1',
               replicant_nodes => []},
             #{core_node => 'data_backup_core2@127.0.0.1',
               replicant_nodes =>
                   [#{node => 'data_backup_replicant@127.0.0.1',
                      streams => 7}]}]
      line: 111
```
2024-07-02 15:15:03 -03:00
Thales Macedo Garitezi ea30d50125 fix(schema registry): avoid atom leak
Fixes https://emqx.atlassian.net/browse/EMQX-12603
2024-07-02 14:01:21 -03:00
Andrew Mayorov 1d5669d008
fix(sessds): tolerate removal of nonexistent gbt entries 2024-07-02 17:15:41 +02:00
Thales Macedo Garitezi 5532f40d83 Merge branch 'release-57' into 20240702-m-sync-r57-mix-umbrella 2024-07-02 11:52:36 -03:00
Thales Macedo Garitezi f64bd313aa
Merge pull request #13263 from thalesmg/mix-umbrella-m-20240612
perf: "mixify" project to improve release speed (part 1)
2024-07-02 11:36:09 -03:00
zhongwencool 55298ab6f3
Merge pull request #13387 from zhongwencool/dont-override-authn-users
fix: don't override authn users when import_user from authn.boostrap_file
2024-07-02 22:33:16 +08:00
lafirest 3f0d59300b
Merge pull request #13348 from lafirest/fix/drop_payload
feat(log): allows custom the encoding of payload in the log
2024-07-02 21:47:48 +08:00
Andrew Mayorov a57917b66b
perf(sessds): rotate through streams with iterators when fetching
This avoids expensive shuffling of the whole list of fetchable streams,
which can be quite long.
2024-07-02 15:42:33 +02:00
Andrew Mayorov 9a4f3f88e3
feat(sessds): allow stream iteration starting from a specific key 2024-07-02 15:40:40 +02:00
Andrew Mayorov dc73b957b3
feat(sessds): use trees to hold streams in session state 2024-07-02 15:39:02 +02:00
Thales Macedo Garitezi 4df2e0be85 fix: bad rebase conflict resolution 2024-07-02 10:21:52 -03:00
zhongwencool 08596f886a feat: add default csv file in authn-built-in-db 2024-07-02 21:18:38 +08:00
zhongwencool 8e904099c7 fix: add boostrap_file/type to post authn_api 2024-07-02 21:18:37 +08:00
zhongwencool 4d912516c8 fix: don't override authn users when import_user from authn.boostrap_file 2024-07-02 21:18:37 +08:00
Thales Macedo Garitezi 8a68f5dada ci: temporarily revert mix release back to old version
This is so we may merge the huge PR as is and work on the fixes later with less conflicts.
2024-07-02 09:47:49 -03:00
Thales Macedo Garitezi bd0c8f0204 fix: bad conflict resolution 2024-07-02 09:47:49 -03:00
Thales Macedo Garitezi a95c9e76a3 Revert "ci: ct testing with mix"
This reverts commit 53bd2af4d23daf3072797dca562aaf56b235fed1.
2024-07-02 09:47:47 -03:00
Thales Macedo Garitezi 89bd69eb50 fix(bridge v1 api): return correct http response code when incompatible 2024-07-02 09:46:06 -03:00
Thales Macedo Garitezi b38e7066a5 ci: ct testing with mix 2024-07-02 09:46:04 -03:00
Thales Macedo Garitezi 8843fcbbf4 perf: use manifest to track proto file compilation 2024-07-02 09:45:47 -03:00
Thales Macedo Garitezi 19f3b030f9 chore: preparing to run common tests / eunit with mix 2024-07-02 09:45:45 -03:00
Thales Macedo Garitezi 8c4a67de31 ci: auto-fix missing newline at end of file 2024-07-02 09:39:50 -03:00
Thales Macedo Garitezi b74828d7ea perf: "mixify" project to improve release speed
Fixes https://emqx.atlassian.net/browse/EMQX-12527
2024-07-02 09:39:48 -03:00
Thales Macedo Garitezi 77ef648573 chore: rm script after usage 2024-07-02 09:39:27 -03:00
Thales Macedo Garitezi 0ece860383 chore: helper script to bootstrap umbrella `mix.exs` files 2024-07-02 09:39:27 -03:00
lafirest dea2bf19b1
Merge pull request #13389 from lafirest/fix/builtin_acl
fix: fix two minor issues of bulti-in authn/authz
2024-07-02 20:19:53 +08:00
Thales Macedo Garitezi 5a0bae2318
Merge pull request #13367 from thalesmg/20240628-r57-test-flaky-authz-cache
test(authz cache): attempt to fix flaky test
2024-07-02 09:14:06 -03:00
Thales Macedo Garitezi 24ac241727
Merge pull request #13380 from thalesmg/20240701-r57-fix-http-bridge-hc-return-value
fix(http action): use correct return value for channel health check
2024-07-02 09:13:53 -03:00
Thales Macedo Garitezi db07a1ebea feat(message transformation): add more read-only fields to context
Fixes https://emqx.atlassian.net/browse/EMQX-12583
2024-07-02 09:13:19 -03:00
firest 3779ddcd65 chore: update changes 2024-07-02 19:35:52 +08:00
firest 686f79c036 fix: fix two minor issues of bulti-in authn/authz
1. the `Derived Key Length` for `pbkdf2` should be a positive integer.
2. fix topics in the authorization rules might be parsed incorrectly
2024-07-02 19:35:48 +08:00
firest dc43fdd5fc chore: update changes 2024-07-02 19:33:36 +08:00
firest a46440d00a feat(log): allows custom the encoding of payload in the log 2024-07-02 19:33:31 +08:00
Andrew Mayorov a5b114a7d4
Merge pull request #13382 from keynslug/fix/EMQX-12421/bump-ehttpc
chore: bump `ehttpc` to 0.4.14
2024-07-02 10:09:56 +02:00
JianBo He 7e0bcd4eda chore: tests in otp26 2024-07-02 15:26:07 +08:00
Thales Macedo Garitezi 317b29451f test(gcp consumer): attempt to stabilize flaky test
```
%%% emqx_bridge_kafka_impl_consumer_SUITE ==> ssl.t_start_and_consume_ok: FAILED
%%% emqx_bridge_kafka_impl_consumer_SUITE ==> {{panic,
     #{msg => "Unexpected result",
       result =>
           {run_stage_failed,error,
               {badmatch,{{1,0},timeout}},
               [{emqx_bridge_kafka_impl_consumer_SUITE,
                    '-t_start_and_consume_ok/1-fun-12-',4,
                    [{file,
                         "/emqx/apps/emqx_bridge_kafka/test/emqx_bridge_kafka_impl_consumer_SUITE.erl"},
                     {line,1184}]},
                {emqx_bridge_kafka_impl_consumer_SUITE,
                    t_start_and_consume_ok,1,
                    [{file,
                         "/emqx/apps/emqx_bridge_kafka/test/emqx_bridge_kafka_impl_consumer_SUITE.erl"},
                     {line,1171}]}]}}},
 [{emqx_bridge_kafka_impl_consumer_SUITE,t_start_and_consume_ok,1,
      [{file,
           "/emqx/apps/emqx_bridge_kafka/test/emqx_bridge_kafka_impl_consumer_SUITE.erl"},
       {line,1240}]},
```
2024-07-01 17:57:17 -03:00
Thales Macedo Garitezi 51a8d3b041
Merge pull request #13381 from thalesmg/20240701-r57-fix-mt-read-user-prop
fix(message transformation): correctly read from user properties in context (r57)
2024-07-01 16:58:46 -03:00
Thales Macedo Garitezi c04e93838f test(eviction agent): attempt to stabilize flaky test
```
%%% emqx_eviction_agent_SUITE ==> t_session_serialization: FAILED
%%% emqx_eviction_agent_SUITE ==>
Failure/Error: ?assertEqual(1, emqx_eviction_agent : session_count ( ))
  expected: 1
       got: 2
      line: 348
```
2024-07-01 16:10:32 -03:00
Andrew Mayorov 97c28553eb
chore: add changelog entry 2024-07-01 20:11:51 +02:00
Andrew Mayorov 8f4b8d2ea2
chore: bump `ehttpc` to 0.4.14
Which includes a fix that prevents `emqtt_pool` from reusing pools
in an inconsistent state.
2024-07-01 20:03:13 +02:00
Thales Macedo Garitezi 59084dbfbe fix(message transformation): correctly read from user properties in context
Port of https://github.com/emqx/emqx/pull/13316 to release-57

Fixes https://emqx.atlassian.net/browse/EMQX-12582
2024-07-01 14:53:42 -03:00
Thales Macedo Garitezi 6dbb561944
Merge pull request #13355 from thalesmg/20240627-r57-fix-connector-api-bad-ssl-config
fix(connector api): handle bad tls config file conversion errors
2024-07-01 14:26:09 -03:00
Thales Macedo Garitezi b14856cf1a refactor: improve error messages 2024-07-01 13:21:17 -03:00
Thales Macedo Garitezi 72664780df fix(http action): use correct return value for channel health check
Fixes https://emqx.atlassian.net/browse/EMQX-12622
2024-07-01 11:17:57 -03:00
dependabot[bot] 7c0e85d239
build(deps): bump the actions group across 1 directory with 3 updates
Bumps the actions group with 3 updates in the / directory: [actions/checkout](https://github.com/actions/checkout), [actions/download-artifact](https://github.com/actions/download-artifact) and [erlef/setup-beam](https://github.com/erlef/setup-beam).


Updates `actions/checkout` from 4.1.2 to 4.1.7
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4.1.2...692973e3d937129bcbf40652eb9f2f61becf3332)

Updates `actions/download-artifact` from 4.1.4 to 4.1.7
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v4.1.4...65a9edc5881444af0b9093a5e628f2fe47ea3b2e)

Updates `erlef/setup-beam` from 1.17.6 to 1.18.0
- [Release notes](https://github.com/erlef/setup-beam/releases)
- [Commits](0a541161e4...a6e26b2231)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: erlef/setup-beam
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-01 14:05:58 +00:00
Ivan Dyachkov 532f04da9d
Merge pull request #13373 from id/0701-sync-release-57
sync release-57
2024-07-01 16:02:29 +02:00
Thales Macedo Garitezi d1e9b097d1
Merge pull request #13365 from thalesmg/20240628-r57-fix-dashboard-add-default-user-concurrently
fix(dashboard): handle add default user race condition
2024-07-01 10:22:32 -03:00
Ivan Dyachkov 505f568c32 chore: bump apps versions 2024-07-01 13:52:27 +02:00
Ivan Dyachkov e28750b522 Merge remote-tracking branch 'upstream/release-57' into 0701-sync-release-57 2024-07-01 13:52:14 +02:00
Kjell Winblad 82bb03a2a3 docs: add change log entry 2024-07-01 13:30:51 +02:00
Kjell Winblad e291dcdd18 fix: default value for max_conn_rate etc should be set to infinity
Before this commit the default value for the fields max_conn_rate,
messages_rate and bytes_rate were not set. This is fixed by setting the
default value to infinity. This breaks the corresponding dashboard
fields (they can not be edited) so the dashboard also needs to be
updated.

Fixes:
https://emqx.atlassian.net/browse/EMQX-12514
2024-07-01 13:16:26 +02:00
lafirest bd075caf56
Merge pull request #13358 from lafirest/fix/authn_reason
fix(events): fixed the reason format of the `authn_complete_event`
2024-07-01 18:46:18 +08:00
lafirest 6c665037de
Merge pull request #13372 from lafirest/fix/gateway_license
fix: limit gateway connections with license
2024-07-01 18:46:05 +08:00
firest b38b4ee5a2 chore: update changes 2024-07-01 16:37:11 +08:00
firest a0644d4612 chore: update app version 2024-07-01 16:32:08 +08:00
Ivan Dyachkov 888ab81ff3
Merge pull request #13363 from id/0628-introduce-env.sh
build: add env.sh to manage builder version in one place
2024-07-01 09:02:07 +02:00
firest b5d507bad8 fix: limit gateway connections with license 2024-06-30 20:06:04 +08:00
Thales Macedo Garitezi ec6e862539 test(authz cache): attempt to fix flaky test
Hypothesis: some race condition involving the previous test case, which uses the same
clientid.

```
Testing apps.emqx.emqx_authz_cache_SUITE: *** FAILED test case 3 of 3 ***
%%% emqx_authz_cache_SUITE ==> t_drain_authz_cache: FAILED
%%% emqx_authz_cache_SUITE ==>
Failure/Error: ?assertEqual([], list_cache ( ClientPid ))
  expected: []
       got: [{{#{qos => 0,action_type => publish,retain => false},<<"t1">>},
              {allow,1719599365019}}]
      line: 72
```
2024-06-28 15:40:55 -03:00
Thales Macedo Garitezi 9215b3710f
Merge pull request #13327 from thalesmg/fix-kprodu-delete-wolff-r57-20240624
fix(kafka and derivatives): add `alias` config to avoid clashes with same topic
2024-06-28 15:22:11 -03:00
Thales Macedo Garitezi b69f298058 fix(dashboard): handle add default user race condition
This can happen at least in tests, when nodes boot concurrently.
2024-06-28 15:18:23 -03:00
Thales Macedo Garitezi 795d280861 fix(connector api): handle bad tls config file conversion errors
Fixes https://emqx.atlassian.net/browse/EMQX-12581
2024-06-28 14:31:31 -03:00
Ivan Dyachkov 6db1ed9e82 build: add env.sh to manage builder version in one place 2024-06-28 17:25:55 +02:00
Thales Macedo Garitezi 9ede62c9b1
Merge pull request #13356 from thalesmg/20240626-m-test-sparkplug-empty-roundtrip
test(schema registry): add test asserting the behavior of empty message roundtrip
2024-06-28 12:08:38 -03:00
Thales Macedo Garitezi 2a9c27d206
Merge pull request #13345 from thalesmg/20240626-r572-fix-validate-schema-reg-name
fix(schema registry api): validate schema name when creating
2024-06-28 12:08:27 -03:00
Thales Macedo Garitezi 063e7657b5
Merge pull request #13344 from thalesmg/20240626-r572-multi-node-bulk-subscribe
fix(client mgmt api): make bulk subscribe work again in clusters
2024-06-28 12:08:16 -03:00
Thales Macedo Garitezi fd49f66267
docs: improve descriptions
Co-authored-by: zmstone <zmstone@gmail.com>
2024-06-28 12:07:30 -03:00
Thales Macedo Garitezi 067beece75 chore: add count to thrown error 2024-06-28 12:06:47 -03:00
JianBo He 89186f46a1 chore: update changes 2024-06-28 14:10:44 +08:00
JianBo He 7cf0e69fdf chore: fix failed tests 2024-06-28 14:07:59 +08:00
firest e8176b80a6 fix(events): fixed the reason format of the `authn_complete_event` 2024-06-28 11:09:28 +08:00
JianBo He b39557f6fd
Merge pull request #13336 from zhongwencool/authn-boostrap-file
feat: support bootstrap_file on authentication for build-in-database
2024-06-28 09:07:53 +08:00
zhongwencool 2c48d7e0f0
Merge pull request #13347 from zhongwencool/improve-check-oom-log
chore: log shutdown reason for check_oom trace log
2024-06-28 08:06:11 +08:00
Thales Macedo Garitezi 79f15b1daa test(schema registry): add test asserting the behavior of empty message roundtrip
Relates to https://emqx.atlassian.net/browse/EMQX-10866
2024-06-27 17:49:57 -03:00
Thales Macedo Garitezi 278c2ef1ec
Merge pull request #13354 from thalesmg/20240626-r572-otp-26-2-5-3
chore: bump otp -> 26.2.5-3
2024-06-27 17:43:25 -03:00
Thales Macedo Garitezi 20c47243ab
Merge pull request #13317 from thalesmg/authz-ignore-metric-m-20240621
feat(authz): add `ignore` metric for each source type
2024-06-27 17:43:06 -03:00
zmstone c2827a03b3
Merge pull request #13352 from zmstone/0627-pin-selenium-docker-image-tag
ci: pin selenium docker image tag 1.0.0
2024-06-27 22:38:32 +02:00
Thales Macedo Garitezi f7d33ff3c0 chore: bump otp -> 26.2.5-3
https://github.com/emqx/emqx-builder/pull/115
2024-06-27 11:36:18 -03:00
Thales Macedo Garitezi e76e94b497 perf(mgmt): optimize bulk unsubscribe when registry is enabled 2024-06-27 10:32:55 -03:00
Thales Macedo Garitezi 0b329dbf06 perf(mgmt): optimize bulk subscribe when registry is enabled 2024-06-27 10:32:55 -03:00
Thales Macedo Garitezi c49900af50 perf(mgmt): optimize clientid lookup when registry is enabled 2024-06-27 10:32:55 -03:00
Andrew Mayorov 3ff9440a01
Merge pull request #13218 from keynslug/feat/EMQX-12468/wal-less
feat(dsrepl): enable WAL-less batch writes
2024-06-27 14:52:22 +02:00
Thales Macedo Garitezi 7b7f44b9ac fix(client mgmt api): make bulk subscribe work again in clusters
Fixes https://emqx.atlassian.net/browse/EMQX-12337
2024-06-27 09:37:55 -03:00
Thales Macedo Garitezi 6f00df6452 fix(schema registry api): validate schema name when creating
Fixes https://emqx.atlassian.net/browse/EMQX-10958
2024-06-27 09:26:41 -03:00
Thales Macedo Garitezi ff8c2bc1d8 feat(authz): add `ignore` metric for each source type
Fixes https://emqx.atlassian.net/browse/EMQX-12411
2024-06-27 09:22:45 -03:00
Thales Macedo Garitezi 4bd0abc93f chore: bump app vsns 2024-06-27 09:22:06 -03:00
Thales Macedo Garitezi 4c3c86e919 chore: bump wolff -> 2.0.0 2024-06-27 09:20:00 -03:00
Thales Macedo Garitezi 164a507899 test(pulsar): add testcase for different producers using the same topic 2024-06-27 09:20:00 -03:00
Thales Macedo Garitezi ed5e6599d9 fix(buffer worker, kafka): send reply when async call fails immediately
Fixes https://emqx.atlassian.net/browse/EMQX-12585
2024-06-27 09:20:00 -03:00
Thales Macedo Garitezi 6023012f8b fix(kafka and derivatives): add `alias` config to avoid clashes with same topic
Fixes https://emqx.atlassian.net/browse/EMQX-12592
2024-06-27 09:20:00 -03:00
zmstone cf8dbdf0a0
docs: Update rel/i18n/emqx_authn_mnesia_schema.hocon 2024-06-27 14:16:40 +02:00
Andrew Mayorov 58b931160f
Merge pull request #13351 from keynslug/ci/pin-debian-x64
build: pin base docker image to stable-20240612-slim
2024-06-27 14:10:28 +02:00
zmstone 8e9eb441db ci: pin selenium docker image tag 1.0.0 2024-06-27 13:56:22 +02:00
zmstone 7e089dce6b
Merge pull request #13349 from zmstone/0627-release-572-to-release-57
0627 release 572 to release 57
2024-06-27 13:52:40 +02:00
zhongwencool d9086139eb
chore: apply suggestions from code review
Co-authored-by: zmstone <zmstone@gmail.com>
2024-06-27 19:31:35 +08:00
Ivan Dyachkov 8a42d664b8
build: pin base docker image to stable-20240612-slim
latest version of 12-slim as of today is configured
to fetch i386 packages
2024-06-27 13:21:06 +02:00
JianBo He 3b21c41690 feat: support to extract the client peersni field to clientinfo 2024-06-27 17:13:10 +08:00
zmstone b6e7d7566d Merge remote-tracking branch 'origin/release-572' into release-57 2024-06-27 11:09:02 +02:00
zmstone 852a135040
Merge pull request #13346 from zmstone/0626-merge-release-572-to-release-57
0626 merge release 572 to release 57
2024-06-27 11:07:44 +02:00
JimMoen ef28579c4a
Merge pull request #13334 from JimMoen/fix-mqtt-username-password-flag
fix(mqtt): check password flag to respect protocol spec
2024-06-27 16:16:53 +08:00
zhongwencool cbaa0b0be0 docs: add password_hash generate document 2024-06-27 15:22:24 +08:00
zhongwencool 6a78951715 chore: log shutdown reason for check_oom trace log 2024-06-27 14:52:22 +08:00
lafirest 68d747b7b9
Merge pull request #13324 from lafirest/feat/oidc-572
feat(sso): add OIDC support
2024-06-27 11:24:05 +08:00
firest 3d398873f1 fix(oidc): return to dashboard when provider calls back
fixed a bug when updating config
2024-06-27 10:22:07 +08:00
zhongwencool 9594b6df32 chore: warning overrided when restart authn 2024-06-27 10:16:04 +08:00
zhongwencool 24d2534641 chore: apply review suggestion 2024-06-27 10:16:04 +08:00
zhongwencool 29076f7eb8 chore: changelog for bootstrap_file/type 2024-06-27 10:16:04 +08:00
zhongwencool 5265c3cc1f feat: support bootstrap_file on build-in-db authn 2024-06-27 10:16:04 +08:00
zmstone 557a843c69 chore: minimize oss/platform diff 2024-06-26 22:48:50 +02:00
zmstone 82e7b75a02 chore: bump app versions 2024-06-26 22:47:18 +02:00
zmstone 98f70ea8d8 Merge remote-tracking branch 'origin/release-572' into release-57 2024-06-26 22:28:08 +02:00
Andrew Mayorov d8963c836e
Merge pull request #13332 from keynslug/ft/EMQX-12571/error-mapping
feat(bridge-s3): provide more meaningful error details in status
2024-06-26 21:13:51 +02:00
Andrew Mayorov e1de18ef10
test(dsrepl): await stable state before running testcase 2024-06-26 20:44:35 +02:00
Andrew Mayorov 30efa1f57e
test(dsrepl): relax crash-recover testcase to tolerate message loss
Which is quite an expected occasion for this kind of stress test.
2024-06-26 20:44:34 +02:00
Andrew Mayorov 3d296abde9
fix(dsrepl): classify ra error conditions more carefully
Most importantly: avoid automatic retries of `shutdown` and `nodedown`
errors as this could easily lead to Raft log entries duplication.
2024-06-26 20:44:34 +02:00
Andrew Mayorov 733751fadd
refactor(dsstore): keep passing `Options` to both prepare + commit 2024-06-26 20:44:34 +02:00
Andrew Mayorov 5b5f33c421
chore(dsstore): resurrect `prepare_batch` entry tracepoint 2024-06-26 20:44:34 +02:00
Andrew Mayorov 8ff48ac5ea
feat(dsrepl): rely on accumulated log size to decide when to flush 2024-06-26 20:44:34 +02:00
Andrew Mayorov b6a249baa9
feat(cth-peer): add brutal `kill/1` facility 2024-06-26 20:44:34 +02:00
Andrew Mayorov 8db70b5bbc
test(dsrepl): add crash-restart-recover testcase
That verifies nothing is lost in the event of abrupt node failures.
2024-06-26 20:44:33 +02:00
Andrew Mayorov ae89b61af0
feat(cth-cluster): make `restart/1` more generic 2024-06-26 20:44:33 +02:00
Andrew Mayorov 5fd5fc76e5
fix(dsstore): ensure backward compatibility 2024-06-26 20:44:33 +02:00
Andrew Mayorov 8538a5a5b6
test(dsrepl): anticipate transitionless membership changes
E.g. when a membership change is applied twice in a row.
2024-06-26 20:44:33 +02:00
Andrew Mayorov 19072414cb
chore: bump `erlang-rocksdb` to 1.8.0-emqx-6 2024-06-26 20:44:33 +02:00
Andrew Mayorov cd0663074e
test(dsrepl): add `add_generation` events into the mix
They usually cause storage layer to perform flushes, and thus enable
testing `handle_flush/1` codepath in different circumstances.
2024-06-26 20:44:33 +02:00
Andrew Mayorov 2180cc7c26
fix(dsstore): avoid storing `cf_refs()` in the RocksDB itself
This is both pointless and confusing.
2024-06-26 20:44:33 +02:00
Andrew Mayorov 80ea2e62f7
fix(stream): ensure that `chain/1` preserves the order 2024-06-26 20:44:32 +02:00
Andrew Mayorov 7895e9cc45
feat(dsstore): make WAL-less mode optional
And make the upper layer choose when to use it.
2024-06-26 20:44:32 +02:00
Andrew Mayorov 0c0757b8c2
feat(dsrepl): enable WAL-less batch writes 2024-06-26 20:44:32 +02:00
Andrew Mayorov 2705226eb5
feat(dsrepl): release log entries occasionally
Also make tracepoints in `apply/3` callback implementation more
uniform.
2024-06-26 20:44:32 +02:00
Andrew Mayorov b6894c18fa
chore(dsrepl): improve tracepoints usability a bit 2024-06-26 20:44:32 +02:00
Thales Macedo Garitezi 483cf6d7af
Merge pull request #13341 from thalesmg/20240626-r572-ci-debug-docker
ci: add debugging info when building for docker tests
2024-06-26 15:16:00 -03:00
Thales Macedo Garitezi 263e654208
Merge pull request #13340 from thalesmg/20240626-r572-fix-docs-conf-load
fix: don't crash if application is already loaded
2024-06-26 15:15:49 -03:00
Thales Macedo Garitezi 7dea8e08b5
Merge pull request #13335 from thalesmg/20240625-test-flaky-resource-expiration-retry-r572
test: attempt to fix flaky test
2024-06-26 15:15:33 -03:00
Thales Macedo Garitezi e81494a132 fix: don't crash if application is already loaded
```
Runtime terminating during boot ({{badmatch,{error,{already_loaded,wolff}}},[{emqx_conf,load,2,[{file,"emqx_conf.erl"},{line,167}]},{lists,foreach_1,2,[{file,"lists.erl"},{line,1686}]},{emqx_conf,dump_schema,2,[{file,"emqx_conf.erl"},{line,150}]},{erl_eval,do_apply,7,[{file,"erl_eval.erl"},{line,746}]},{erl_eval,expr,6,[{file,"erl_eval.erl"},{line,494}]},{erl_eval,exprs,6,[{file,"erl_eval.erl"},{line,136}]},{init,start_it,1,[]},{init,start_em,1,[]}]})
```
2024-06-26 13:41:32 -03:00
Thales Macedo Garitezi ef89afae3e ci: add debugging info when building for docker tests 2024-06-26 13:41:07 -03:00
Thales Macedo Garitezi 954adc71c4 test: attempt to fix flaky test
https://github.com/emqx/emqx/actions/runs/9662725303/job/26653594859?pr=13328#step:6:186

```
%%% emqx_resource_SUITE ==> t_expiration_retry: FAILED
%%% emqx_resource_SUITE ==> {{panic,
     #{msg => "Unexpected result",
       result =>
           {run_stage_failed,error,
               {badmatch,{ok,timeout}},
               [{emqx_resource_SUITE,'-do_t_expiration_retry/0-fun-12-',0,
                    [{file,
                         "/__w/emqx/emqx/apps/emqx_resource/test/emqx_resource_SUITE.erl"},
                     {line,2569}]},
                {emqx_resource_SUITE,do_t_expiration_retry,0,
                    [{file,
                         "/__w/emqx/emqx/apps/emqx_resource/test/emqx_resource_SUITE.erl"},
                     {line,2518}]}]}}},
 [{emqx_resource_SUITE,do_t_expiration_retry,0,
      [{file,"/__w/emqx/emqx/apps/emqx_resource/test/emqx_resource_SUITE.erl"},
       {line,2594}]},
  {test_server,ts_tc,3,[{file,"test_server.erl"},{line,1793}]},
  {test_server,run_test_case_eval1,6,[{file,"test_server.erl"},{line,1302}]},
  {test_server,run_test_case_eval,9,[{file,"test_server.erl"},{line,1234}]}]}
```
2024-06-26 13:40:49 -03:00
Ivan Dyachkov f7b1baf1ef
Merge pull request #13343 from id/0626-pin-base-docker-image-572
build: pin base docker image to stable-20240612-slim
2024-06-26 16:46:49 +02:00
Ivan Dyachkov 21f8cdd4c9
Merge pull request #13342 from id/0626-pin-base-docker-image
build: pin base docker image to stable-20240612-slim
2024-06-26 16:44:38 +02:00
Ivan Dyachkov f6f2ea7451 build: pin base docker image to stable-20240612-slim
latest version of 12-slim as of today is configured
to fetch i386 packages
2024-06-26 15:49:10 +02:00
Ivan Dyachkov 5e6d4d53a9 build: pin base docker image to stable-20240612-slim
latest version of 12-slim as of today is configured
to fetch i386 packages
2024-06-26 15:46:57 +02:00
zhongwencool fec5db18c1
Merge pull request #13315 from zhongwencool/keepalive-multiplier
feat: improve keepalive_multiplier and keepalive_check_interval
2024-06-26 19:35:14 +08:00
zmstone 98e4e45df7
Merge pull request #13339 from zmstone/0626-release-v5.7.1
0626 release v5.7.1
2024-06-26 13:28:07 +02:00
zmstone c240e6b729 docs: add changelog for enterprise 5.7.1 2024-06-26 12:16:39 +02:00
zhongwencool 1735f8deef chore: apply review suggestion 2024-06-26 18:08:17 +08:00
zmstone ef1b6d2a55 chore: keep enterprise edition version updated as well 2024-06-26 11:40:49 +02:00
zmstone e79e615c15 docs: add changelog for v5.7.1 2024-06-26 11:15:13 +02:00
zmstone 465ae507d8 chore: update release version to v5.7.1 2024-06-26 10:49:59 +02:00
zmstone af9bfc21cb
Merge pull request #13312 from zmstone/0621-fix-regex_extract-docs
doc: fix regex_extract function doc
2024-06-26 10:48:40 +02:00
zmstone 7f73f27d56
docs: fix typo 2024-06-26 10:18:08 +02:00
zhongwencool 4942f6f75a feat: improve keepalive_multiplier and keepalive_check_interval 2024-06-26 15:43:48 +08:00
zmstone debad00e82
Merge pull request #13330 from zmstone/0625-chore-improve-cut.sh
chore: improve rel/cut.sh
2024-06-26 08:11:04 +02:00
JianBo He b5486b8908
Merge pull request #13333 from Kinplemelon/kinple/upgrade-dashboard
chore(dashboard): bump dashboard version to v1.9.1 & e1.7.1
2024-06-26 14:04:01 +08:00
Kinplemelon 66d60d10bb ci(ui-tests): update link to ce version doc on the dashboard 2024-06-26 10:17:00 +08:00
Thales Macedo Garitezi 21c01f32ff
Merge pull request #13305 from kjellwinblad/kjell/redis_conn_always_time_out_no_username_password/EMQX-12557
fix: redis connector should not timeout because no username and password
2024-06-25 16:06:21 -03:00
Andrew Mayorov da214be5a1
test(bridge-s3): adapt testcase to different CI environment 2024-06-25 18:35:53 +02:00
Andrew Mayorov 0eedab3d76
chore: add changelog entry 2024-06-25 18:35:53 +02:00
Andrew Mayorov 10e9fed22b
Merge pull request #13326 from keynslug/fix/ct/api-clients-flaky
test(api-clients): refactor suite to isolate flakiness
2024-06-25 18:26:42 +02:00
JimMoen ed130fdc57
test: MQTT CONNECT flags check 2024-06-25 23:25:42 +08:00
JimMoen 02a9885aa5
fix(mqtt): check password flag to respect protocol spec 2024-06-25 23:25:36 +08:00
JimMoen 983f02ea1b
refactor: separate CONNECT flags validation funcs 2024-06-25 23:15:39 +08:00
Kjell Winblad 130571b56e fix: code improvements thanks to comments from @thalesmg 2024-06-25 12:00:36 -03:00
Kjell Winblad 31509f02cc docs: add change log entry 2024-06-25 12:00:36 -03:00
Kjell Winblad 6190192cbc fix: redis connector should not timeout because no username and password
A redis connector of type single or sentinel always got a timeout error
when doing the connector test in the dashboard if no username or
password was provided. This commit makes sure that the user instead get
an informative error message. Additionally, this commit adds more
more error information for all redis connector types.

Fixes:
https://emqx.atlassian.net/browse/EMQX-12557
2024-06-25 12:00:36 -03:00
Kinplemelon 299934bb1e chore(dashboard): bump dashboard version to v1.9.1 & e1.7.1 2024-06-25 22:55:50 +08:00
Thales Macedo Garitezi cc89a20ed9
Merge pull request #13318 from thalesmg/test-flaky-gcp-consu-r57-20240621
test(gcp consumer): stabilize flaky test
2024-06-25 11:52:20 -03:00
Andrew Mayorov 486a041adf
feat(bridge-s3): also map credentials / aggreg upload errors 2024-06-25 16:51:07 +02:00
Andrew Mayorov fb9afd8313
feat(bridge-s3): beautify posix write errors 2024-06-25 16:51:07 +02:00
Andrew Mayorov f3ffbd4710
feat(bridge-s3): provide more meaningful error details in status 2024-06-25 16:51:06 +02:00
Andrew Mayorov 98e4ea6fde
feat(bridge-s3): make validation errors more readable
And also turn them into schema-level validations, instead of
bridge-level error conditions.
2024-06-25 16:51:06 +02:00
Thales Macedo Garitezi a2e8d49847
Merge pull request #13328 from thalesmg/fix-greptime-grpcbox-opts-r57-20240624
fix(greptime): correctly define grpc options for `grpcbox_channel`
2024-06-25 11:06:20 -03:00
Thales Macedo Garitezi 1a497bcaf2 fix(greptime): correctly define grpc options for `grpcbox_channel`
Will probably fix CI flakiness.
2024-06-25 09:47:31 -03:00
Thales Macedo Garitezi c9ec5ac87b test(gcp consumer): stabilize flaky test
https://github.com/emqx/emqx/actions/runs/9614788348/job/26526973635?pr=13317#step:5:1463

```
%%% emqx_bridge_gcp_pubsub_consumer_SUITE ==> t_connection_down_before_starting: FAILED
%%% emqx_bridge_gcp_pubsub_consumer_SUITE ==> {{panic,
     #{msg => "Unexpected result",
       result =>
           {run_stage_failed,error,
               {assertMatch,
                   [{module,emqx_bridge_gcp_pubsub_consumer_SUITE},
                    {line,1451},
                    {expression,"health_check ( Config )"},
                    {pattern,"{ ok , connecting }"},
                    {value,{ok,disconnected}}]},
               [{emqx_bridge_gcp_pubsub_consumer_SUITE,
                    '-t_connection_down_before_starting/1-fun-11-',4,
                    [{file,
                         "/emqx/apps/emqx_bridge_gcp_pubsub/test/emqx_bridge_gcp_pubsub_consumer_SUITE.erl"},
                     {line,1451}]},
                {emqx_bridge_gcp_pubsub_consumer_SUITE,
                    t_connection_down_before_starting,1,
                    [{file,
                         "/emqx/apps/emqx_bridge_gcp_pubsub/test/emqx_bridge_gcp_pubsub_consumer_SUITE.erl"},
                     {line,1427}]}]}}},
 [{emqx_bridge_gcp_pubsub_consumer_SUITE,t_connection_down_before_starting,1,
      [{file,
           "/emqx/apps/emqx_bridge_gcp_pubsub/test/emqx_bridge_gcp_pubsub_consumer_SUITE.erl"},
       {line,1462}]},
  {test_server,ts_tc,3,[{file,"test_server.erl"},{line,1793}]},
  {test_server,run_test_case_eval1,6,[{file,"test_server.erl"},{line,1302}]},
  {test_server,run_test_case_eval,9,[{file,"test_server.erl"},{line,1234}]}]}
```
2024-06-25 09:36:55 -03:00
zmstone e93edefef7 chore: improve rel/cut.sh 2024-06-25 09:43:28 +02:00
ieQu1 9f30da334f
Merge pull request #13248 from ieQu1/dev/EMQX-12491-local-backend
replace builtin DS backend with builtin_local and builtin_raft
2024-06-24 23:07:57 +02:00
ieQu1 d349f84f04
fix(ds): Apply remarks 2024-06-24 20:20:40 +02:00
Andrew Mayorov d12b985507
test(api-clients): refactor suite to isolate flakiness 2024-06-24 16:54:20 +02:00
zmstone ea077eac62
Merge pull request #13320 from zmstone/0622-sync-app-vsn
chore: minimize oss/platform diff
2024-06-24 16:32:24 +02:00
zmstone 6b3f293ac6 ci: test dashboard against latest version 2024-06-24 15:31:13 +02:00
zmstone af0fe1db89 ci: do not trigger build on e tag pushes in oss repo 2024-06-24 15:30:03 +02:00
zmstone 5d1608f34b chore: minimize oss/platform diff 2024-06-24 15:30:03 +02:00
Thales Macedo Garitezi debf1e6cd5
Merge pull request #13316 from thalesmg/fix-mt-read-user-prop-m-20240621
fix(message transformation): correctly read from user properties in context
2024-06-24 09:31:48 -03:00
firest abc255bb02 fix(oidc): make CI happy 2024-06-24 18:11:02 +08:00
firest 892420e2c6 feat(oidc): be more compatible with okta 2024-06-24 16:51:54 +08:00
firest ddb197951e feat(oidc): implement JWKS, private_key_jwt, DPoP 2024-06-24 16:51:43 +08:00
firest 9c0df3c0a8 feat(oidc): support the PKCE extension 2024-06-24 16:51:32 +08:00
firest 5e2693c9b4 feat(oidc): implement session management 2024-06-24 16:51:20 +08:00
firest 512b4b9cbb feat(sso): add OIDC support 2024-06-24 16:50:58 +08:00
JianBo He 23acbb664e
Merge pull request #13258 from HJianBo/fix-boot-order-for-gws
fix: gateway app must depends on all auth apps
2024-06-24 16:31:27 +08:00
zmstone f9e17d6c25
Merge pull request #13269 from JimMoen/improve-plugin-behavior
fix: mark fresh install to cp the default configuration file directly
2024-06-24 09:17:25 +02:00
Ivan Dyachkov 4a81c3ac18
Merge pull request #13298 from qzhuyan/fix/william/hot-conf-disable-partial-chain
fix(tls): disable partial_chain in hot config
2024-06-24 09:02:07 +02:00
JianBo He 14e2ed7be1
Merge pull request #13314 from zhongwencool/flaky-cluster-rpc-SUITE
test: add more debug msg to flaky cluster_rpc SUITE
2024-06-24 13:36:03 +08:00
ieQu1 c0472a06f1
test(ds): Set initial conditions in repl. suite explicitly 2024-06-22 02:55:05 +02:00
Thales Macedo Garitezi 6682004dc8
Merge pull request #13319 from thalesmg/20240621-sync-r57-m
sync release-57 to master
2024-06-21 17:44:08 -03:00
Thales Macedo Garitezi ec83d999bf Merge remote-tracking branch 'origin/release-57' into 20240621-sync-r57-m 2024-06-21 14:11:08 -03:00
ieQu1 9a58d71378
fix(ds): Move DS backend supervision trees to their own apps 2024-06-21 18:22:04 +02:00
ieQu1 3d69ec496a
fix(schema): Transform config of `singleton' discovery_strategy 2024-06-21 17:16:25 +02:00
ieQu1 d7d878fd43
test(ds): Fix emqx standalone test profile selection 2024-06-21 17:16:25 +02:00
ieQu1 8aa27488b6
test: Disable certain DS-related suites in CE 2024-06-21 17:16:24 +02:00
ieQu1 1d3b1868fb
test(ds): Use close_db API 2024-06-21 17:16:24 +02:00
ieQu1 b2f7815a7f
test(ds): Don't start raft explicitly 2024-06-21 17:16:24 +02:00
ieQu1 3851fc189f
fix(ds): Avoid reverse dependencies from storage to repl. layer 2024-06-21 17:16:24 +02:00
ieQu1 bc915216a0
feat(ds): Support metrics for builtin_local backend 2024-06-21 17:16:24 +02:00
ieQu1 be6c5e172f
fix(ds): Disable DS management APIs for builtin_local backend 2024-06-21 17:16:24 +02:00
ieQu1 99c9b56cf3
feat(ds_buffer): Add `ls' function to list all local buffers 2024-06-21 17:16:24 +02:00
ieQu1 5a8818edf3
feat(ds): Add schema for builtin_local backend 2024-06-21 17:16:24 +02:00
ieQu1 4484f30021
feat(ds_schema): Add schema for builtin_local backend 2024-06-21 17:16:24 +02:00
ieQu1 8990b1312b
refactor(ds_schema): Rename backend builtin -> builtin_raft 2024-06-21 17:16:24 +02:00
ieQu1 ea48b1265d
refactor(ds_schema): Extract common builtin fields 2024-06-21 17:16:24 +02:00
ieQu1 abe41de19b
refactor(ds_schema): builtin_local_buffer -> builtin_buffer 2024-06-21 17:16:24 +02:00
ieQu1 ecb172b07e
refactor(ds): Rename egress metrics to 'buffer' 2024-06-21 17:16:24 +02:00
ieQu1 09c3ae795d
refactor(ds_raft): Replace egress server with common emqx_ds_buffer 2024-06-21 17:16:24 +02:00
ieQu1 a0fbd37e58
refactor(emqx): Use emqx_ds_backends application 2024-06-21 17:16:24 +02:00
ieQu1 ef09cfcd71
feat(ds): Add `emqx_ds_backends` application 2024-06-21 17:16:24 +02:00
ieQu1 279619fc80
feat(ds): Add `builtin_local' backend 2024-06-21 17:16:24 +02:00
ieQu1 a8ea0ae4e5
refactor(ds): Extract DS replication layer to a separate application 2024-06-21 17:16:24 +02:00
ieQu1 63f1856a2c
feat(ds): Dynamic backend registration 2024-06-21 17:16:24 +02:00
ieQu1 83dc8f4d77
fix(ds): Fix return values of emqx_ds_storage_layer functions 2024-06-21 17:16:23 +02:00
ieQu1 a18d1987a2
test(ds): Add a helper function for diffing messages 2024-06-21 17:16:23 +02:00
Ilia Averianov f1b8c356a6
Merge pull request #13299 from savonarola/0617-shared-sub-leader-poc
feat(queue): implement PoC version of session ↔️ shared group leader interaction
2024-06-21 16:45:17 +03:00
Thales Macedo Garitezi 28c7d94bd2 fix(message transformation): correctly read from user properties in context
Fixes https://emqx.atlassian.net/browse/EMQX-12582
2024-06-21 09:39:22 -03:00
Ilya Averyanov db28a042d5 feat(queue): handle renew_lease_timeout 2024-06-21 15:18:37 +03:00
zhongwencool 75a524c916 test: add more debug msg to flaky cluster_rpc SUITE 2024-06-21 18:04:24 +08:00
Ilya Averyanov 2096755ad6 feat(queue): reorganize group sm callbacks and methods 2024-06-21 13:01:38 +03:00
Ilya Averyanov b9c5911883 feat(queue): implement `find_leader_timeout` event and so the `connecting` group_sm state 2024-06-21 12:22:17 +03:00
SergeTupchiy fb266fbf8c
Merge pull request #13300 from SergeTupchiy/EMQX-12195-cluster-link-conf-backup
cluster link conf backup
2024-06-21 11:42:57 +03:00
zmstone 8a99995810 docs: fix regex_extract function doc 2024-06-21 09:25:09 +02:00
JianBo He d8e6c07ca0 chore: fix failed tests 2024-06-21 11:04:23 +08:00
JianBo He a8af90f912 chore: add changes 2024-06-21 09:39:14 +08:00
JianBo He 08f085d823 fix: gateway app must depends on all auth apps 2024-06-21 09:39:14 +08:00
Ilya Averyanov 979fb58e50 feat(queue): use tp to trace new lease events 2024-06-20 21:12:15 +03:00
Ilya Averyanov 1205e34650 feat(queue): remove too useless header file 2024-06-20 20:48:56 +03:00
JimMoen acc8bf3405
Merge pull request #13222 from JimMoen/fix-will-qos-retain-flag-check
fix: check willretain and willqos when WillFlag set to `true`
2024-06-21 01:28:23 +08:00
Ivan Dyachkov ba4fb0d3f9
Merge pull request #13290 from kjellwinblad/kjell/format_rule_cli/EMQX-12548
fix: do not crash when showing rule unsing the cmd interface
2024-06-20 14:55:33 +02:00
zmstone 2a0071aa01
Merge pull request #13295 from thalesmg/test-flaky-greptime-mkII-r57-20240619
test(greptime): attempt to fix flaky tests (attempt without driver patch)
2024-06-20 14:49:21 +02:00
Ilya Averyanov be175d205c feat(queue): add JIRA task links for TODOs 2024-06-20 15:38:16 +03:00
Ilya Averyanov a9c976b6c1 feat(queue): fix notes about the usage of agent<->leader protocol-related data structures 2024-06-20 15:24:25 +03:00
Ilya Averyanov d0cff63ed6 feat(queue): remove unused hrl-guard 2024-06-20 15:18:47 +03:00
Ilya Averyanov a92460d38f feat(queue): improve hints for macro clauses 2024-06-20 15:17:08 +03:00
zmstone 24bc54035a
Merge pull request #13306 from zmstone/0620-ci-pull-haproxy-image-from-ghcr
ci: pull haproxy image from ghcr
2024-06-20 13:46:47 +02:00
zmstone fcc9f5cca4
Merge pull request #13304 from zmstone/0620-minor-refactoring
chore: minimize oss/platform diff
2024-06-20 13:46:31 +02:00
SergeTupchiy 4cdfb1453a
Merge pull request #13307 from SergeTupchiy/EMQX-10974-heal-partition-when-majority-alive
chore: upgrade ekka to 0.19.5 (mria 0.8.8)
2024-06-20 13:56:53 +03:00
zmstone 23df47664a ci: pull haproxy image from ghcr 2024-06-20 11:58:59 +02:00
Serge Tupchii ac8762be10 chore: upgrade ekka to 0.19.5 (mria 0.8.8)
mria 0.8.8 heals a network partition once majority of core nodes are alive.
Previously, the autoheal worked only when all core nodes were reachable.

Fixes: EMQX-10974
2024-06-20 12:53:58 +03:00
William Yang 464a0a82f0 fix(tls): move default_root_fun to ?CONST_MOD_V1 2024-06-20 11:38:52 +02:00
zmstone 7d32275ebe chore: minimize oss/platform diff 2024-06-20 10:36:01 +02:00
zmstone f969a4ef5e
Merge pull request #13296 from zmstone/0619-sync-release-57-to-master
0619 sync release 57 to master
2024-06-20 10:33:52 +02:00
Kjell Winblad 12859b8959 fix: handle yet another action format 2024-06-20 10:03:49 +02:00
JianBo He 3a276e8875
Merge pull request #13302 from HJianBo/bump-version
chore: cut v5.7.1-alpha.1
2024-06-20 11:47:00 +08:00
JimMoen 675abd7512
test: will retain and willqos in connect flags 2024-06-20 10:32:15 +08:00
JimMoen cf9d6943d5
fix: check willretain and willqos when WillFlag set to `true` 2024-06-20 10:32:15 +08:00
JianBo He c307c1dfc2 chore: cut v5.7.1-alpha.1 2024-06-20 09:40:42 +08:00
Ilya Averyanov 6da10036dc feat(queue): fix dialyzer issues 2024-06-19 22:25:53 +03:00
Ilya Averyanov a4bbab4aa2 feat(queue): document general entity layout 2024-06-19 22:24:20 +03:00
JimMoen ff742d926a
fix: `?SLOG` with msg field 2024-06-20 02:18:26 +08:00
Serge Tupchii 71f5eaf11e fix(data_backup): import `cluster.links` conf 2024-06-19 20:47:06 +03:00
Serge Tupchii ef5cf4fac3 chore(clusterlink): fix comment 2024-06-19 20:46:00 +03:00
Ilya Averyanov 2b0146663a feat(queue): add smoke test for ds shared subs 2024-06-19 19:32:23 +03:00
Ilya Averyanov e3c4816035 feat(queue): move group subscription state machine to its own module 2024-06-19 19:22:10 +03:00
Thales Macedo Garitezi 9559ba2f06 test: remove unnecessary lines 2024-06-19 13:22:02 -03:00
William Yang 8d04545f03 test(tls): root_fun is set even when partial_chain is false 2024-06-19 17:34:04 +02:00
William Yang 41239ae766 fix(tls): disable partial_chain in hot config 2024-06-19 17:03:05 +02:00
zmstone 021b6b3902 Merge remote-tracking branch 'origin/release-57' into 0619-sync-release-57-to-master 2024-06-19 15:06:41 +02:00
zmstone 02a6ee1ef4
Merge pull request #13279 from zmstone/0617-json-decode-payload-for-map_to_redis_hset_args
fix(redis): json decode if arg for map_to_redis_hset_args is string
2024-06-19 14:55:21 +02:00
zmstone 213e4785e7 Merge remote-tracking branch 'origin/release-57' into 0619-sync-release-57-to-master 2024-06-19 14:54:48 +02:00
JimMoen a6fa3e82d9
fix: prevent use pd 2024-06-19 20:15:07 +08:00
JimMoen b7b2a08399
fix: match plugin_not_found reason 2024-06-19 20:15:07 +08:00
JimMoen 28293284a7
fix: let crash when plugin not found in cluster 2024-06-19 20:15:07 +08:00
JimMoen 19e039e0d2
fix: mark fresh install to cp the default configuration file directly 2024-06-19 20:15:07 +08:00
Thales Macedo Garitezi ff2e6e1434 test(greptime): revert driver patch to test ci again 2024-06-19 09:12:30 -03:00
zmstone 95d387a790
Merge pull request #13294 from zmstone/0618-per-release-edition-code-injection
0618 per release edition code injection
2024-06-19 11:53:57 +02:00
zmstone f0e5721959 refactor: make dialyzer happy 2024-06-19 10:42:08 +02:00
SergeTupchiy 0d098a01ef
Merge pull request #13293 from SergeTupchiy/EMQX-12345-reindex-retained-msgs-on-import
reindex retained msgs on import
2024-06-19 11:23:08 +03:00
Thales Macedo Garitezi ffec1c7fe0 fix(greptime): attempt patch for cleaning up channels when worker terminates 2024-06-18 22:16:03 -03:00
Thales Macedo Garitezi 9dd419d822 test(greptime): attempt to fix flaky tests
```
=WARNING REPORT==== 18-Jun-2024::12:42:04.739109 ===
    reason: no_endpoints
    msg: failed_to_start_greptimedb_connector
    client: #{protocol => http,
              pool => <<"connector:greptimedb:emqx_bridge_greptimedb_SUITE">>,
              cli_opts =>
                  [{endpoints,[{http,"toxiproxy",4001}]},
                   {pool_size,2},
                   {pool_type,random},
                   {auto_reconnect,1},
                   {gprc_options,#{sync_start => true,
                                   connect_timeout => 5000}},
                   {dbname,"public"},
                   {auth,{basic,#{password => <<"******">>,
                                  username => "greptime_user"}}},
                   {https_enabled,false}]}
    connector: <<"connector:greptimedb:emqx_bridge_greptimedb_SUITE">>
```
2024-06-18 18:23:22 -03:00
zmstone 54fc605cc5 refactor: move schema injection from hrl to erl 2024-06-18 22:22:53 +02:00
zmstone a53fa977df refactor: delete an unused macro 2024-06-18 22:22:48 +02:00
Thales Macedo Garitezi e69ba33420
Merge pull request #13291 from thalesmg/fix-ds-mgmt-node-down-r57-20240618
fix(dsreplmeta): check site status when fetching shard info
2024-06-18 15:14:08 -03:00
Ilya Averyanov bca743054b feat(queue): implement backbones of queue agent, leader and leader registry 2024-06-18 21:03:51 +03:00
Thales Macedo Garitezi 4c54ab6379 test: remove tests per review request 2024-06-18 13:08:19 -03:00
Serge Tupchii 12363cec4a chore: add changelog 2024-06-18 18:22:51 +03:00
Kjell Winblad 4a318f8f51 style: fix type problem found by dialyzer 2024-06-18 17:02:26 +02:00
Serge Tupchii baa7996289 fix(data_backup): allow exporting `ram_copies` Mnesia tables
Currently, ram tables can be used for message retainer.
2024-06-18 17:31:33 +03:00
Serge Tupchii 60882a616e fix(data_backup): re-index retained messages after importing 2024-06-18 17:31:19 +03:00
Kjell Winblad 3c8c8ddf36 docs: add change log entry 2024-06-18 15:42:06 +02:00
Thales Macedo Garitezi 6bde6aa711
Merge pull request #13280 from thalesmg/fix-plugin-elixir-r57-20240617
fix(plugins): do not stop Elixir protected apps
2024-06-18 10:41:12 -03:00
Thales Macedo Garitezi 8ce16fd7d9 fix(dsreplmeta): check site status when fetching shard info
Fixes https://emqx.atlassian.net/browse/EMQX-12356
2024-06-18 10:40:09 -03:00
Kjell Winblad a4f855108c fix: do not crash when showing rule unsing the cmd interface
Before the change the command line command

    $ bin/emqx ctl rules show rule_0hyd

would crash if the rule had bridge actions. This has now been fixed by
adding a handler for printing  bridge actions.

Fixes:
https://emqx.atlassian.net/browse/EMQX-12548
2024-06-18 15:17:25 +02:00
Kjell Winblad 3f7723b2dc
Merge pull request #13274 from kjellwinblad/kjell/add_ssl_to_rocksdb/EMQX-12289
feat: add SSL support to RocketMQ connector
2024-06-18 09:38:28 +02:00
Ivan Dyachkov 43cca6c9f8
Merge pull request #13286 from id/0718-sync-docker-docs-with-official-image
docs(docker): sync README.md with the official image docs
2024-06-18 08:48:36 +02:00
Ivan Dyachkov 4e83ca34ce docs(docker): sync README.md with the official image docs 2024-06-18 08:16:38 +02:00
ieQu1 a5110da37c
Merge pull request #13283 from thalesmg/sync-r57-m-20240617
sync release-57 to master
2024-06-18 00:10:50 +02:00
Thales Macedo Garitezi 20cffb54d4 Merge branch 'release-57' into sync-r57-m-20240617 2024-06-17 17:10:12 -03:00
Thales Macedo Garitezi 6897f0141b fix(plugins): do not stop Elixir protected apps
On one hand, Elixir plugins might include Elixir itself, when targetting a non-Elixir EMQX
release.  If, on the other hand, the EMQX release already includes Elixir, we shouldn't
stop Elixir nor IEx, or the running IEx shell will break.
2024-06-17 16:42:23 -03:00
Ilia Averianov ad993437aa
Merge pull request #13278 from savonarola/0617-release-57-sync
Sync release-57
2024-06-17 21:25:00 +03:00
zmstone 9479c8d33b fix(redis): json decode if arg for map_to_redis_hset_args is string 2024-06-17 20:19:53 +02:00
Andrew Mayorov eede9f349e
Merge pull request #13276 from keynslug/fix/ds/inherited-lts-lost
fix(dsstore): persist inherited LTS trie
2024-06-17 20:25:31 +03:00
zmstone ae22a64157
Merge pull request #13277 from zmstone/0617-handle-kafka-message_too_large-return
0617 handle kafka message too large return
2024-06-17 19:15:33 +02:00
Kjell Winblad 0cbbae9655 fix: make fixes due to comments from @thalesmg 2024-06-17 19:06:12 +02:00
Kjell Winblad 6d36f4a228 docs: add change log entry 2024-06-17 19:06:12 +02:00
Kjell Winblad c39c544c96 feat: add SSL support to RocketMQ connector 2024-06-17 19:06:12 +02:00
Thales Macedo Garitezi b64f0c0ca7
Merge pull request #13231 from thalesmg/mt-test-endpoint-r57-20240611
feat(message transformation): implement dryrun endpoint
2024-06-17 13:11:39 -03:00
Thales Macedo Garitezi 240bb09070
Merge pull request #13275 from thalesmg/test-flaky-sk-r57-20240617
test: attempt to fix flaky test
2024-06-17 13:01:08 -03:00
Ilya Averyanov f8e6aab86f Merge branch 'release-57' into 0617-release-57-sync
* release-57:
  chore(auth,http): cache REs for parsing URIs
  fix(auth,http): improve URI handling
  chore: revert ULOG/ELOG
  test: generate dispatch.eterm in dashboard test
  docs: refine change log
  feat: make the dashboard restart quicker
  chore: fix typo
  fix(http authz): handle unknown content types in responses
  chore: change types of mysql and mongodb fields to `template()`
  fix(client mgmt api): allow projecting `client_attrs` from client fields
  fix(emqx_rule_funcs): expose regex_extract function to rule engine
2024-06-17 18:53:39 +03:00
Andrew Mayorov 82588fbc35
chore(dsstore): refine module and callback typespecs 2024-06-17 17:53:39 +02:00
Andrew Mayorov 4f7b13e634
chore: add changelog entry 2024-06-17 17:53:39 +02:00
Andrew Mayorov 05d97397d3
fix(dsstore): use correct comparison when walking over generations 2024-06-17 17:53:39 +02:00
Andrew Mayorov 22009bcc58
test(dsstore): verify that inherited TLS trie is persisted 2024-06-17 17:53:38 +02:00
Andrew Mayorov 68f6556856
fix(dsstore): persist inherited LTS trie
Before this commit, inherited trie was actually only kept in memory
cache.

Also simplify storage backend behaviour around inheriting previous
generation's legacy.
2024-06-17 17:53:38 +02:00
SergeTupchiy 830266b4d5
Merge pull request #13126 from SergeTupchiy/EMQX-11967-cross-cluster-route-replication-syncer-actor
cluster linking
2024-06-17 18:52:46 +03:00
zmstone 04439fc51f docs: rename PR number of changelog
PR 13079 was merged too soon
2024-06-17 17:27:25 +02:00
zmstone 3ac4ddcbe3 fix(kafka): handle message_too_large
bump 'failed' counter
2024-06-17 17:27:25 +02:00
zmstone 5126373862 ci: create a kafka topic with smalle max.message.bytes config 2024-06-17 17:27:25 +02:00
zmstone 00dfdc22cf chore: pin Kafka client wolff 0.10.5 2024-06-17 17:27:25 +02:00
zhongwencool 3143475769
Merge pull request #13271 from zmstone/0617-docs-add-changelog-for-pr-13191
docs: add changelog for PR 13191
2024-06-17 22:16:49 +08:00
zhongwencool 5ab4b321a0
Merge pull request #13267 from zhongwencool/use-redbug-for-trace
chore(debug): use redbug for default trace tools
2024-06-17 22:10:18 +08:00
Thales Macedo Garitezi fb492e3dc5
Merge pull request #13264 from thalesmg/fix-postgres-disabled-prepared-r57-20240614
fix(postgres): authn/authz/batch requests when prepared statements are disabled
2024-06-17 11:05:05 -03:00
Thales Macedo Garitezi 5665a4917c
Merge pull request #13266 from thalesmg/fix-s3-release-app-r57-20240614
fix: add `emqx_s3` to `reboot_lists.eterm`
2024-06-17 10:48:12 -03:00
Thales Macedo Garitezi ec4f462684 refactor: apply review requests 2024-06-17 10:39:32 -03:00
Thales Macedo Garitezi 1464094967 test: attempt to fix flaky test
```
%%% emqx_persistent_session_ds_SUITE ==> t_session_discard_persistent_to_persistent: FAILED
%%% emqx_persistent_session_ds_SUITE ==> {noproc,{gen_server,call,[snabbkaffe_collector,flush_trace,infinity]}}
```
2024-06-17 10:34:57 -03:00
Ilia Averianov 420cd84cf1
Merge pull request #13273 from savonarola/0617-fix-url-parse-5.7
fix(auth,http): improve URI handling
2024-06-17 16:32:51 +03:00
Thales Macedo Garitezi b71212b022 refactor: apply review comments 2024-06-17 09:40:33 -03:00
Thales Macedo Garitezi f5eb3e7471
Merge pull request #13250 from thalesmg/ds-singleton-m-20240613
feat: enforce singleton discovery strategy when using DS `builtin_local` backend
2024-06-17 09:34:05 -03:00
Ilya Averyanov 19c9f0d76f chore(auth,http): cache REs for parsing URIs 2024-06-17 14:42:29 +03:00
Ilya Averyanov f7ac829f28 fix(auth,http): improve URI handling 2024-06-17 14:42:29 +03:00
Serge Tupchii a905a6048c chore(clusterlink): rename link `upstream` field to `name` 2024-06-17 12:24:51 +03:00
Serge Tupchii a95a08efd3 test(clusterlink): add more test cases 2024-06-17 12:24:51 +03:00
Serge Tupchii 44c37571cc fix(clusterlink): ignore not_registered error 2024-06-17 12:24:51 +03:00
Serge Tupchii 00f912928f fix: fix emqx_external_broker:forward/1 spec 2024-06-17 12:24:51 +03:00
Andrew Mayorov 179870c573 chore: remove author-specific gitignore stuff
Which was accidentally committed.
2024-06-17 12:24:51 +03:00
Andrew Mayorov ed16ff07df refactor(broker): simplify external broker behaviour 2024-06-17 12:24:51 +03:00
Serge Tupchii d282c61120 feat(clusterlink): update only necessary resources when a link config is changed 2024-06-17 12:24:50 +03:00
Serge Tupchii 5304ca1563 fix(clusterlink): add emqx_cluster_link app to mix.exs/rebar.config.erl 2024-06-17 12:24:47 +03:00
Serge Tupchii ff16521d4f fix(clusterlink): add schema descriptions, fix dialyzer warnings, add resource_opts 2024-06-17 12:23:52 +03:00
Serge Tupchii 94e81ba812 feat(clusterlink): implement actor config handler 2024-06-17 12:23:52 +03:00
Serge Tupchii c871b37453 fix(clusterlink): add link topics schema validator 2024-06-17 12:23:52 +03:00
Andrew Mayorov 780a0bf807 fix(cluster-link): clear exit signal of failed-to-connect client 2024-06-17 12:23:52 +03:00
Andrew Mayorov d0df4de2a3 test(cluster-link): add e2e replication actor GC testcase 2024-06-17 12:23:52 +03:00
Andrew Mayorov c4840b30d2 fix(cluster-link): deduplicate routes down to dest cluster 2024-06-17 12:23:52 +03:00
Andrew Mayorov ede35df24a fix(cluster-link): cancel heartbeats on client down 2024-06-17 12:23:52 +03:00
Andrew Mayorov e0604e3af6 fix(cluster-link): anticipate clients may occasionally retry 2024-06-17 12:23:52 +03:00
Andrew Mayorov 0219b8bd4d feat(cluster-link): add simple replication actor GC process 2024-06-17 12:23:52 +03:00
Andrew Mayorov 7fccb5dbc9 test(topic): add more `intersection/2` testcases 2024-06-17 12:23:52 +03:00
Andrew Mayorov 7b8f466adf feat(topic): avoid `lists:reverse` when intersecting 2024-06-17 12:23:52 +03:00
Andrew Mayorov 24be189728 fix(topic): respect special topic rules when intersecting 2024-06-17 12:23:51 +03:00
Andrew Mayorov de1ac131f7 test(cluster-link): fix test suite setup 2024-06-17 12:23:51 +03:00
Serge Tupchii 58eaf07627 fix(clusterlink): valide config to disallow duplicated cluster links 2024-06-17 12:23:51 +03:00
Andrew Mayorov 54d51d0982 test(cluster-link): draft basic integration test suite 2024-06-17 12:23:51 +03:00
Andrew Mayorov e9c24090d4 fix(cluster-link): avoid starting ps syncer if persistence disabled 2024-06-17 12:23:51 +03:00
Andrew Mayorov 036c7e8492 test(cluster-link): adapt extrouter testsuite to new APIs 2024-06-17 12:23:51 +03:00
Andrew Mayorov 45eda4f3b9 fix(cluster-link): adapt heartbeat / reincarnation handling to new API 2024-06-17 12:23:51 +03:00
Andrew Mayorov 43d114546c feat(cluster-link): preserve replication actor state in pdict 2024-06-17 12:23:51 +03:00
Andrew Mayorov 5771a41a32 fix(cluster-link): ensure replication actor bootstraps do heartbeats 2024-06-17 12:23:51 +03:00
Andrew Mayorov d4b449c6e1 feat(cluster-link): implement replication actor heartbeats 2024-06-17 12:23:51 +03:00
Serge Tupchii faa4420e1f fix(clusterlink): improve actor error handling
Add status and error reason to the actor state, report alarms.
2024-06-17 12:23:51 +03:00
Serge Tupchii 21711c6e0d fix(clusterlink): communicate bootstrap requirements via actor handshake
`session_present` flag is not reliable to decide whether bootstrap is needed if durable sessions is enabled.
In this case, the client session may survive cluster restart while all the external routes are lost, as they are not persistent.
2024-06-17 12:23:51 +03:00
Serge Tupchii d5e82cdfac refactor(clusterlink): avoid unnecessary `maybe_` external_broker CB names 2024-06-17 12:23:51 +03:00
Serge Tupchii d578ac3f9e fix(clusterlink): match correct timer ref in router actor 2024-06-17 12:23:51 +03:00
Serge Tupchii b1aeb35370 feat(clusterlink): implement actor init handshake 2024-06-17 12:23:51 +03:00
Serge Tupchii ac19cf89df chore(clusterlink): remove code related to the rejected coordinator-based implementation 2024-06-17 12:23:51 +03:00
Serge Tupchii e26e7acaa1 refactor(clusterlink): use `emqx_bridge_mqtt_lib:clientid_base/1` to construct routesync client id 2024-06-17 12:23:51 +03:00
Serge Tupchii e7305c62ee feat(clusterlink): replicate shared subscription and persistent session routes 2024-06-17 12:23:51 +03:00
Serge Tupchii f036b641eb feat(clusterlink): integrate node local routes replication and message forwarding 2024-06-17 12:23:51 +03:00
Serge Tupchii 7df91d852c feat(clusterlink): integrate node local syncer/actor implementation
- support multiple cluster links in extrouter
 - apply extrouter ops on 'message.publish' hook
 - fix several minor bugs
2024-06-17 12:23:51 +03:00
Andrew Mayorov cbd01ae818 feat(clusterlink): add node-local route sync actor implementation 2024-06-17 12:23:51 +03:00
Andrew Mayorov 7b95273218 feat(routesync): make syncer a bit more generic and reusable 2024-06-17 12:23:51 +03:00
Andrew Mayorov 5bd9ee5c7f feat(utils): add `emqx_utils_ets:keyfoldl/3` function
Designed to be used with `bag` / `duplicate_bag` tables.
2024-06-17 12:23:51 +03:00
Andrew Mayorov 4097585f5d fix(clusterlink): ensure extrouter works on replicants
This is sort of a quick fix to make things safe, but it will likely be
a subject to the same drawbacks as the regular router in high-latency
deployments: reduced throughput.
2024-06-17 12:23:51 +03:00
Andrew Mayorov a53524c826 fix(cth-cluster): fix occasional case clauses during cluster bootup 2024-06-17 12:23:51 +03:00
Andrew Mayorov 2dd99c5a08 feat(clusterlink): add facility to reconstruct remote routing table 2024-06-17 12:23:51 +03:00
Serge Tupchii f08342c704 feat: cluster link prototype WIP 2024-06-17 12:23:48 +03:00
lafirest 98a54994c0
Merge pull request #13196 from lafirest/fix/rules_len
fix(authz_mnesia): add a soft limit in the API for the length of ACL rules
2024-06-17 15:47:59 +08:00
zmstone 735245977b docs: add changelog for PR 13191 2024-06-17 09:45:41 +02:00
zhongwencool 17809a5803 chore: fix dialyzer warning 2024-06-17 14:07:30 +08:00
firest 1716852057 fix(authz_mnesia): improve field names and changes 2024-06-17 10:09:25 +08:00
zhongwencool a49e5877ec chore(debug): use redbug for default trace tools 2024-06-17 09:28:23 +08:00
zmstone 8daaf7b727
Merge pull request #13233 from zmstone/0611-expose-regex_extract-func
fix(emqx_rule_funcs): expose regex_extract function to rule engine
2024-06-16 16:16:48 +02:00
zmstone 2b7f3a597f
Merge pull request #13245 from qzhuyan/merge/william/sync-rel57-to-master
sync release57 to master
2024-06-15 09:13:55 +02:00
zhongwencool d433fc7c30
Merge pull request #13236 from zhongwencool/bug-schema-validation
fix: some minor bug fixes
2024-06-15 06:40:28 +08:00
zhongwencool aadbcb69a7
Merge pull request #13242 from zhongwencool/dashboard-start-improve
feat:  make the dashboard restart quicker
2024-06-15 06:24:22 +08:00
Thales Macedo Garitezi 198ccd320b fix: add `emqx_s3` to `reboot_lists.eterm`
Otherwise, it's unconditionally started as a permanent application instead of being
controlled by `emqx_machine`.

```sh
ͳ rg start_boot _build/emqx-enterprise/rel/emqx/releases/5.7.0-g4e6be8a6/start.script | rg emqx_s3
     {apply,{application,start_boot,[emqx_s3,permanent]}},
```
2024-06-14 15:06:18 -03:00
Thales Macedo Garitezi 6e702cd16c fix(postgres): fix usage by authn/authz modules when prepared statements are disabled
Fixes https://emqx.atlassian.net/browse/EMQX-12550
2024-06-14 12:19:46 -03:00
zmstone 626aae6edf chore: fix bad conflict resolution 2024-06-14 16:57:53 +02:00
zhongwencool d95f17fe77 chore: revert ULOG/ELOG 2024-06-14 22:11:27 +08:00
Thales Macedo Garitezi fd5e844cc1 fix(postgres): correctly handle batch queries with disabled prepared statements
Fixes https://emqx.atlassian.net/browse/EMQX-12549
2024-06-14 11:10:21 -03:00
zhongwencool f713f13b2c test: generate dispatch.eterm in dashboard test 2024-06-14 21:52:58 +08:00
Thales Macedo Garitezi 9b3c806ba7 feat(message transformation): implement dryrun endpoint
Follow up to https://github.com/emqx/emqx/pull/13199
2024-06-14 10:19:36 -03:00
Thales Macedo Garitezi 62ecdb8ad0
Merge pull request #13246 from thalesmg/doc-changelog-nit-m-20240613
docs: minor changelog improvement
2024-06-14 09:19:28 -03:00
Thales Macedo Garitezi 378a16b4fb feat: enforce singleton discovery strategy when using DS `builtin_local` backend
Fixes https://emqx.atlassian.net/browse/EMQX-12493
2024-06-14 09:18:35 -03:00
zmstone 945ea785ae docs: refine change log 2024-06-14 13:12:08 +02:00
zhongwencool a6e3a09118 feat: make the dashboard restart quicker 2024-06-14 18:22:34 +08:00
JimMoen 0f0e7d18db
Merge pull request #13261 from JimMoen/fix-typo
chore: fix typo
2024-06-14 16:55:35 +08:00
JimMoen 6823c79ae0
chore: fix typo 2024-06-14 16:04:11 +08:00
William Yang b86d631744 test: fix tc t_handle_outing_non_utf8_topic 2024-06-14 08:17:19 +02:00
William Yang d39b8caff9 Merge branch 'release-57' into merge/william/sync-rel57-to-master 2024-06-14 08:17:09 +02:00
lafirest afd4b46f72
Merge pull request #13225 from lafirest/fix/mysql_redact
fix(auth): redact sensitive data for the authn/authz APIs
2024-06-14 09:19:21 +08:00
Thales Macedo Garitezi 01635722e9
docs: improve descriptions
Co-authored-by: ieQu1 <99872536+ieQu1@users.noreply.github.com>
2024-06-13 18:34:44 -03:00
Thales Macedo Garitezi 52e6c88941 feat: enforce singleton discovery strategy when using DS `builtin_local` backend
Fixes https://emqx.atlassian.net/browse/EMQX-12493
2024-06-13 17:04:23 -03:00
Thales Macedo Garitezi cba5c7bb45 refactor: rm dead code 2024-06-13 16:57:34 -03:00
Thales Macedo Garitezi 4d876f2af2 chore: bump ekka -> 0.19.4
https://github.com/emqx/ekka/pull/236
2024-06-13 16:35:58 -03:00
Thales Macedo Garitezi 3adf64e637
Merge pull request #13240 from thalesmg/ds-cluster-purge-m-20240612
feat: support purging durable sessions during cluster purge
2024-06-13 09:30:18 -03:00
Thales Macedo Garitezi 5b73670252 docs: minor changelog improvement
Addresses https://github.com/emqx/emqx/pull/13232#discussion_r1637889964
2024-06-13 09:14:37 -03:00
Thales Macedo Garitezi b6613e7b27
Merge pull request #13232 from thalesmg/mt-changelog-m-20240611
docs: add changelog for message transformation
2024-06-13 09:11:07 -03:00
Thales Macedo Garitezi 6ccf1dcbf9
Merge pull request #13238 from thalesmg/fix-authz-http-content-type-handling-r57-20240612
fix(http authz): handle unknown content types in responses
2024-06-13 09:10:43 -03:00
Thales Macedo Garitezi 62cf277cd7
Merge pull request #13235 from thalesmg/fix-template-types-r57-20240611
chore: change types of mysql and mongodb fields to `template()`
2024-06-13 09:08:40 -03:00
Thales Macedo Garitezi c81a3ebc0a
Merge pull request #13234 from thalesmg/fix-clients-api-client-attrs-union-r57-20240611
fix(client mgmt api): allow projecting `client_attrs` from client fields
2024-06-13 09:08:29 -03:00
William Yang 1664ea4ad4 Revert: TLS partial-chain and keyUsage #12955 #12977
This reverts commit 28b17a2562.
This reverts commit 01467246fc.
This reverts commit c3f8ba5762.
This reverts commit 1a4a4bb3a5.
This reverts commit fb30207ef3.
This reverts commit 337c230e79.
This reverts commit 3a674f44f1.
This reverts commit 70ffd77f99.
This reverts commit 03b0935564.
This reverts commit 650cf4b27e.
This reverts commit 43ad665dcf.
This reverts commit a29a43e5fc.
This reverts commit 4e9c1ec0c9.
This reverts commit 8eb463c58d.
This reverts commit 90430fa66d.
This reverts commit eb1ab9adfe.
This reverts commit 8bc3a86f63.
This reverts commit fa4357ce89.
This reverts commit 0b95a08d32.
2024-06-13 13:46:45 +02:00
zhongwencool 1dd4b6de5e
Merge pull request #13241 from zhongwencool/add-with-mfa-option-for-log
feat: add hidden option to record MFA and line in the log
2024-06-13 19:26:10 +08:00
William Yang 723144199e
Merge pull request #13211 from qzhuyan/fix/william/rel57/ee-tls
Fix/william/rel57/ee tls
2024-06-13 13:19:44 +02:00
Andrew Mayorov 129bc6b013
Merge pull request #13243 from keynslug/chore/bridge-s3/schema-req-fields
chore(s3): make schema fields with defaults optional
2024-06-13 13:46:20 +03:00
Andrew Mayorov 0f53b33417
chore(s3): make schema fields with defaults optional 2024-06-13 11:57:36 +02:00
zhongwencool 0eee2edd28 test: fix api_config SUITE failed 2024-06-13 14:55:24 +08:00
zhongwencool 2b1fa1711b fix: observer command crash when can't find object code 2024-06-13 14:55:23 +08:00
zhongwencool 623845d07d fix: don't allow set active_n to negative int 2024-06-13 14:55:23 +08:00
zhongwencool 825bfe4717 fix: load bad configs return unknown msg 2024-06-13 14:55:23 +08:00
zhongwencool 5d3f464ec3 fix: ws/wss's max_frame_size should > 0 2024-06-13 14:55:23 +08:00
JimMoen e1536961ce
Merge pull request #13237 from JimMoen/EMQX-12167-add-missing-schema
refactor: mv metrics macros in hrl file
fix: metrics macro with description
2024-06-13 14:50:17 +08:00
zhongwencool 800a79adde test: test failed with_mfa 2024-06-13 09:50:52 +08:00
Thales Macedo Garitezi 2c264d9a4b fix(http authz): handle unknown content types in responses
Fixes https://emqx.atlassian.net/browse/EMQX-12530
2024-06-12 14:31:12 -03:00
zhongwencool c72b455a83 feat: add hidden option to record MFA and line in the log is very useful for debug. 2024-06-12 22:51:45 +08:00
Thales Macedo Garitezi d0e6f22a79 feat: support purging durable sessions during cluster purge
Fixes https://emqx.atlassian.net/browse/EMQX-12405
2024-06-12 11:19:53 -03:00
Thales Macedo Garitezi 0c805e049e docs: add changelog for message transformation 2024-06-12 09:52:25 -03:00
Thales Macedo Garitezi fe303231cf
Merge pull request #13230 from thalesmg/sync-r57-m-20240611
sync release-57 to master
2024-06-12 08:55:43 -03:00
JimMoen daeb10151b
chore: fix typos 2024-06-12 19:06:34 +08:00
JimMoen cde4cb1358
fix: metrics macro with description 2024-06-12 19:06:33 +08:00
JimMoen 756797b258
refactor: gen metric schema with desc from macros 2024-06-12 19:04:39 +08:00
JimMoen 263d2dbae2
fix: inc metric `'client.auth.anonymous'` when client anonymous 2024-06-12 19:04:39 +08:00
JimMoen 9a78a6f640
refactor: mv metrics macros in hrl file 2024-06-12 19:04:29 +08:00
JimMoen cbac4019b3
fix: rm havn't used counter idx 2024-06-12 19:01:50 +08:00
Thales Macedo Garitezi 46ab3be1f4 chore: change types of mysql and mongodb fields to `template()`
Fixes https://emqx.atlassian.net/browse/EMQX-12395
2024-06-11 17:25:53 -03:00
Thales Macedo Garitezi 0874768c1d fix(client mgmt api): allow projecting `client_attrs` from client fields
Fixes https://emqx.atlassian.net/browse/EMQX-12511
2024-06-11 17:14:33 -03:00
zmstone 8a283b1cc0
Merge pull request #13180 from zmstone/0604-optimize-tcp-ssl-connection-data-send-performance
0604 optimize tcp ssl connection data send performance
2024-06-11 22:06:57 +02:00
zmstone 09f91159c9 fix(emqx_rule_funcs): expose regex_extract function to rule engine
previoulsy only available in variform expressions,
now made available for rule-engine
2024-06-11 21:31:13 +02:00
zmstone 51810c6919
Merge pull request #13229 from zmstone/0611-auth-with-raw-cert
feat(authn): support `${cert_pem}` placeholder
2024-06-11 21:16:01 +02:00
Thales Macedo Garitezi db572d35a7 Merge remote-tracking branch 'origin/release-57' into sync-r57-m-20240611 2024-06-11 15:34:54 -03:00
Thales Macedo Garitezi 7cb57606bf
Merge pull request #13210 from thalesmg/sv-check-referenced-types-r57-20240607
feat(schema validation): check references schema names and types before changing config
2024-06-11 15:34:14 -03:00
zmstone 751f7a24e9 feat(authn): support ${cert_pem} placeholder 2024-06-11 19:54:24 +02:00
Thales Macedo Garitezi 337009c3a0 fix: declare `emqx_schema_registry` as a dependency of `emqx_schema_validation` 2024-06-11 14:03:27 -03:00
Thales Macedo Garitezi 0f9c3b4cea feat(schema validation): check references schema names and types before changing config
Fixes https://emqx.atlassian.net/browse/EMQX-12368
2024-06-11 14:03:26 -03:00
Thales Macedo Garitezi 03b226248a feat(schema registry): add check for inner types
Currently, only `protobuf` has any.
2024-06-11 13:50:11 -03:00
Thales Macedo Garitezi c70e8252fe fix: declare `emqx_schema_registry` as a dependency of `emqx_message_transformation` 2024-06-11 13:35:02 -03:00
Thales Macedo Garitezi b2d716909f
Merge pull request #13200 from thalesmg/update-erlazure-no-gen-server-m-20240606
chore: refactor azure blob connector to use new `erlazure` without `gen_server`
2024-06-11 13:30:14 -03:00
Thales Macedo Garitezi 686bcc8a48
Merge pull request #13207 from thalesmg/republish-metrics-m-20240607
fix(rule actions): check `republish` action result for metrics
2024-06-11 13:29:58 -03:00
Thales Macedo Garitezi 2c6aa80b3c
Merge pull request #13221 from thalesmg/refactor-sv-topic-index-r57-20240610
refactor(schema validation): module organization and position indexing
2024-06-11 13:29:48 -03:00
Thales Macedo Garitezi 83ff07ade0
Merge pull request #13199 from thalesmg/message-transformation-r57-20240604
feat: implement message transformation
2024-06-11 13:29:25 -03:00
Thales Macedo Garitezi ab5329be02
Merge pull request #13220 from thalesmg/refactor-channel-hc-opt-r57-20240610
fix: remove another redundant health check
2024-06-11 12:22:43 -03:00
firest 46a51bd92b chore: update changes 2024-06-11 21:34:37 +08:00
Andrew Mayorov 2f0eb3560b
Merge pull request #13227 from keynslug/fix/EMQX-12533/bad-tpl
fix(bridge-s3): validate aggreg key template before adding a channel
2024-06-11 15:39:12 +03:00
Andrew Mayorov 57ecf4de9c
chore: add changelog entry 2024-06-11 13:21:41 +02:00
Andrew Mayorov d4fb812352
fix(aggreg): anticipate and handle delivery startup errors 2024-06-11 13:21:41 +02:00
Andrew Mayorov 29fc30ea69
fix(bridge-s3): validate aggreg key template before adding a channel 2024-06-11 13:21:41 +02:00
Andrew Mayorov fb0da9848c
feat(tpl): add separate `placeholders/1` function
The purpose is to have a clearer view of placeholders used in a
template, without going the usual `render(Template, #{})` route that is
actually subtly misleading: it won't mention that `${}` / `${.}`
placeholder has been used.

Also unify handling of `${}` / `${.}` in a couple of places.
2024-06-11 11:42:43 +02:00
Kjell Winblad 9d22089104
Merge pull request #13173 from kjellwinblad/kjell/pgsql_timestamp_encode_etc/EEC-1036
fix(pgsql connector): handle prepared statement already exists
2024-06-11 10:53:30 +02:00
William Yang 44258204bd chore: move tls_certs test helper to apps/emqx 2024-06-11 10:06:18 +02:00
firest e64f60b73f fix(auth): redact sensitive data for the authn/authz APIs 2024-06-11 16:05:11 +08:00
zhongwencool b657dc537c
Merge pull request #13156 from savonarola/0529-fix-dashboard-monitor
fix(dashboard_monitor): correctly merge old and new sample data
2024-06-11 10:33:15 +08:00
Thales Macedo Garitezi 3f77c6f64e
Merge pull request #13219 from thalesmg/otp-26-2-5-2-r57-20240610
chore: bump OTP to 26.2.5-2
2024-06-10 17:01:25 -03:00
Thales Macedo Garitezi 05ebb17cd6 refactor: index positions rather than names
Addresses https://github.com/emqx/emqx/pull/13199#discussion_r1633096025
2024-06-10 15:54:37 -03:00
Thales Macedo Garitezi 5eff4a7544 refactor(schema validation): improve api and module organization
To conform to comment from another PR:
https://github.com/emqx/emqx/pull/13199#discussion_r1632658742

... since schema validation is the "inspiration" for message transformation.
2024-06-10 15:46:28 -03:00
Thales Macedo Garitezi d93c8540c8 feat: pass along peername down to transformation context 2024-06-10 15:35:35 -03:00
Thales Macedo Garitezi 6e0ef893f4 feat: pass along client attributes down to message transformation context 2024-06-10 15:27:04 -03:00
Thales Macedo Garitezi 3c501e4f2a fix: remove another redundant health check
Fixes https://emqx.atlassian.net/browse/EMQX-12521
2024-06-10 15:13:34 -03:00
Thales Macedo Garitezi 1a20a40218
Merge pull request #13209 from thalesmg/rm-redundant-hc-r57-20240607
chore: remove redundant health check call
2024-06-10 14:58:48 -03:00
Thales Macedo Garitezi e586178479 chore: refactor azure blob connector to use new `erlazure` without `gen_server`
https://github.com/dkataskin/erlazure/pull/43 removes unnecessary usage of `gen_server`
from the driver.
2024-06-10 13:42:28 -03:00
Thales Macedo Garitezi f6680ed063 chore: bump OTP to 26.2.5-2
https://github.com/emqx/otp/pull/54
2024-06-10 13:41:23 -03:00
Thales Macedo Garitezi 5629fe60c1 refactor: index positions rather than names 2024-06-10 13:33:22 -03:00
Thales Macedo Garitezi 8c7a7cf9db refactor: apply review remarks 2024-06-10 11:17:13 -03:00
Thales Macedo Garitezi e54cf2f218 refactor: use option to skip rendering as string 2024-06-10 10:49:39 -03:00
Thales Macedo Garitezi d34558954d refactor: improve api and module organization 2024-06-10 10:40:53 -03:00
zmstone e6ece52575
Merge pull request #13217 from zmstone/0610-chore-refine-code
chore: cosmetic changes
2024-06-10 15:11:19 +02:00
Thales Macedo Garitezi 4aa1c3842f fix: declare `emqx` as a dependency in `.app.src` 2024-06-10 09:53:29 -03:00
Thales Macedo Garitezi aa416cc0ad docs: fix stale comments and dates 2024-06-10 09:53:02 -03:00
zmstone 7a09b0470d chore: cosmetic changes 2024-06-10 14:22:25 +02:00
zmstone f911347318
Merge pull request #13216 from zmstone/0610-mqtt-bridge-respect-clientid-prefix
fix(bridge/mqtt): respect client ID prefix
2024-06-10 14:07:30 +02:00
Kjell Winblad a885f0b41a test(emqx_bridge_pgsql_SUITE): call test janitor 2024-06-10 13:45:27 +02:00
zmstone 7b2b2b527c docs: add changelog for pr #13216 2024-06-10 10:48:04 +02:00
William Yang 64d7d2484f chore(tls): move changelog again 2024-06-10 10:36:13 +02:00
William Yang 2ca7e9c55e chore: rename changelog 2024-06-10 10:34:30 +02:00
William Yang a1aa9a4375 fix(ee): emqx no longer deps on emqx_auth_ext 2024-06-10 10:32:01 +02:00
zmstone f8cb5161a9
Merge pull request #13212 from zmstone/0609-upgrade-system-monitor
0609 upgrade system monitor
2024-06-10 10:29:11 +02:00
zmstone bb9fb10ec5
Merge pull request #13213 from zmstone/0609-syn-release-57-to-master
0609 syn release 57 to master
2024-06-10 10:28:59 +02:00
zmstone 4347f3de3e fix(bridge/mqtt): respect client ID prefix 2024-06-10 10:27:45 +02:00
William Yang 95e515d585 docs: add emqx_auth_ext_schema.hocon 2024-06-10 10:25:47 +02:00
William Yang 76cfc309a9 feat(tls): partial_chain not required 2024-06-10 10:25:44 +02:00
William Yang 7c37bf9965 feat(tls): ee only: TLS partial_chain and Keyusage 2024-06-10 10:24:48 +02:00
William Yang 2b50610a60 chore: fix nit for spellcheck 2024-06-10 09:55:51 +02:00
William Yang 1040c752db docs: Apply suggestions from code review
Co-authored-by: Zaiming (Stone) Shi <zmstone@gmail.com>
2024-06-10 09:55:49 +02:00
William Yang 38115f9233 chore: update doc for `partial_chain` and `verify_peer_ext_key_usage` 2024-06-10 09:55:45 +02:00
William Yang e60380d205 chore: fix nit 2024-06-10 09:55:12 +02:00
William Yang e9b813d8ef chore: fix test 2024-06-10 09:54:54 +02:00
William Yang 1739bc0c24 feat(partial_chain): gateway support 2024-06-10 09:54:44 +02:00
zmstone 45dd7816d7 Merge remote-tracking branch 'origin/release-57' 2024-06-09 10:11:15 +02:00
zmstone 672173c7fd chore: pin system_monitor 3.0.5 2024-06-09 10:06:15 +02:00
zmstone 5da5ce1aae docs: fix a typo in change log 2024-06-08 18:05:14 +02:00
William Yang abbf2ef62f chore(TLS-chain-test): update for OTP 26 2024-06-08 00:16:06 +02:00
William Yang 9e196680de chore: add changelog 2024-06-08 00:16:04 +02:00
William Yang 221b748b0f test(partial_chain): update tcs for OTP-25 2024-06-08 00:16:01 +02:00
William Yang 463d1a1875 fix(test): tls_verify_partial_chain 2024-06-08 00:15:54 +02:00
William Yang 788cdbc6dd fix(listener): remove partial_chain in wss opts 2024-06-08 00:15:51 +02:00
William Yang 3fc99315e0 chore: happy elvis 2024-06-08 00:15:45 +02:00
William Yang c5dccdf526 feat(tls): update schema for TLS keyusage 2024-06-08 00:15:43 +02:00
William Yang aa25e3badd fix(tls): undefined keyusage 2024-06-08 00:15:39 +02:00
William Yang 9e5cfea8c0 test(tls): verify peer keyusage 2024-06-08 00:15:36 +02:00
William Yang c5657029ab feat(config): partial_chain 2024-06-08 00:15:34 +02:00
William Yang f7ff9496e6 test: port listener tls partial_chain 2024-06-08 00:15:31 +02:00
William Yang 1ce13242a8 feat(tls): port partial_chain, part 1 2024-06-08 00:15:28 +02:00
Kjell Winblad c13631102e fix(PgSQL connector): typo in function name 2024-06-07 19:40:18 +02:00
Andrew Mayorov b2f027c974
Merge pull request #13197 from keynslug/fix/EMQX-12522/conv-ssl
fix(bridge-s3): pass SSL options through `convert_certs/2`
2024-06-07 19:45:53 +03:00
zmstone 15fbb966a0
Merge pull request #13198 from zmstone/0606-merge-release-57-to-master
0606 merge `release-57` to `master`
2024-06-07 16:23:26 +02:00
Thales Macedo Garitezi 39615e1cb6 fix(rule actions): check `republish` action result for metrics
Fixes https://emqx.atlassian.net/browse/EMQX-12328
2024-06-07 11:17:43 -03:00
Thales Macedo Garitezi 28a3c77e88 chore: remove redundant health check call
Since `emqx_resource_manager:channel_health_check` already does a base resource health
check, the call was repeated.
2024-06-07 11:07:12 -03:00
zmstone 9574b33832
Merge branch 'master' into 0606-merge-release-57-to-master 2024-06-07 15:21:34 +02:00
Ivan Dyachkov 590569776d
Merge pull request #13205 from emqx/dependabot/github_actions/actions-f50227a1a2
build(deps): bump the actions group across 1 directory with 11 updates
2024-06-07 14:39:44 +02:00
Thales Macedo Garitezi 2828e8a5c5
Merge pull request #13201 from thalesmg/fix-fmt-m-20240606
ci: fix `make fmt` to take into account checkouts and elixir deps
2024-06-07 09:20:57 -03:00
Kjell Winblad e63dcc84b0 fix: unused variable and better error message 2024-06-07 12:20:42 +02:00
Kjell Winblad a3f3f96781 test(emqx_bridge_v2_pgsql_SUITE): fix broken test case
We have to delete the connector and action created by the previous step
of the test case so we don't get a name conflict.
2024-06-07 12:03:34 +02:00
dependabot[bot] f07aaac256
build(deps): bump the actions group across 1 directory with 11 updates
Bumps the actions group with 11 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [actions/checkout](https://github.com/actions/checkout) | `4.1.2` | `4.1.6` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `4.3.1` | `4.3.3` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `4.1.4` | `4.1.7` |
| [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) | `3.2.0` | `3.3.0` |
| [docker/login-action](https://github.com/docker/login-action) | `3.1.0` | `3.2.0` |
| [slackapi/slack-github-action](https://github.com/slackapi/slack-github-action) | `1.25.0` | `1.26.0` |
| [hashicorp/setup-terraform](https://github.com/hashicorp/setup-terraform) | `3.0.0` | `3.1.1` |
| [actions/cache](https://github.com/actions/cache) | `4.0.1` | `4.0.2` |
| [erlef/setup-beam](https://github.com/erlef/setup-beam) | `1.17.5` | `1.17.6` |
| [coverallsapp/github-action](https://github.com/coverallsapp/github-action) | `2.2.3` | `2.3.0` |
| [ossf/scorecard-action](https://github.com/ossf/scorecard-action) | `2.3.1` | `2.3.3` |



Updates `actions/checkout` from 4.1.2 to 4.1.6
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](9bb56186c3...a5ac7e51b4)

Updates `actions/upload-artifact` from 4.3.1 to 4.3.3
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](5d5d22a312...65462800fd)

Updates `actions/download-artifact` from 4.1.4 to 4.1.7
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](c850b930e6...65a9edc588)

Updates `docker/setup-buildx-action` from 3.2.0 to 3.3.0
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](2b51285047...d70bba72b1)

Updates `docker/login-action` from 3.1.0 to 3.2.0
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](e92390c5fb...0d4c9c5ea7)

Updates `slackapi/slack-github-action` from 1.25.0 to 1.26.0
- [Release notes](https://github.com/slackapi/slack-github-action/releases)
- [Commits](6c661ce588...70cd7be8e4)

Updates `hashicorp/setup-terraform` from 3.0.0 to 3.1.1
- [Release notes](https://github.com/hashicorp/setup-terraform/releases)
- [Changelog](https://github.com/hashicorp/setup-terraform/blob/main/CHANGELOG.md)
- [Commits](a1502cd9e7...651471c36a)

Updates `actions/cache` from 4.0.1 to 4.0.2
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](ab5e6d0c87...0c45773b62)

Updates `erlef/setup-beam` from 1.17.5 to 1.17.6
- [Release notes](https://github.com/erlef/setup-beam/releases)
- [Commits](2f0cc07b4b...0a541161e4)

Updates `coverallsapp/github-action` from 2.2.3 to 2.3.0
- [Release notes](https://github.com/coverallsapp/github-action/releases)
- [Commits](3dfc556739...643bc377ff)

Updates `ossf/scorecard-action` from 2.3.1 to 2.3.3
- [Release notes](https://github.com/ossf/scorecard-action/releases)
- [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md)
- [Commits](0864cf1902...dc50aa9510)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: docker/setup-buildx-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: docker/login-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: slackapi/slack-github-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: hashicorp/setup-terraform
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: erlef/setup-beam
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: coverallsapp/github-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: ossf/scorecard-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-07 07:50:25 +00:00
Ivan Dyachkov eea399e3ed
Merge pull request #13204 from id/0607-ci-keep-release-branch-green
ci: trigger reruns of failed checks on release-57 branch as well as master
2024-06-07 09:46:40 +02:00
Ivan Dyachkov 381ed6a451 ci: trigger reruns of failed checks on release-57 branch as well as master 2024-06-07 08:57:18 +02:00
JimMoen 78a196e215
Merge pull request #13189 from JimMoen/fix-apply-sqlserver-template
fix(utils_sql): improve insert sql regular expression
2024-06-07 13:50:19 +08:00
lafirest eb215726d5
Merge pull request #13195 from lafirest/fix/typos
fix: fix typos
2024-06-07 09:04:16 +08:00
Thales Macedo Garitezi ef36350bf6 feat: implement message transformation
Fixes https://emqx.atlassian.net/browse/EMQX-12517
2024-06-06 17:51:08 -03:00
Thales Macedo Garitezi c0c5545c21 ci: fix `make fmt` to take into account checkouts and elixir deps 2024-06-06 16:53:30 -03:00
Andrew Mayorov 5672326ca8
chore: add changelog entry 2024-06-06 19:37:38 +02:00
Andrew Mayorov 8a85d7cb5a
fix(bridge-s3): pass SSL options through `convert_certs/2` 2024-06-06 19:37:38 +02:00
Andrew Mayorov c17c788438
feat(connector): allow delegate `pre_config_update` to impls 2024-06-06 19:37:34 +02:00
zmstone ebf17c8143 Merge remote-tracking branch 'origin/release-57' into 0606-merge-release-57-to-master 2024-06-06 17:43:36 +02:00
firest 3ae26c8a54 chore: update changes 2024-06-06 18:13:24 +08:00
firest 5532c7b0a6 fix(authz_mnesia): add a soft limit in the API for the length of ACL rules 2024-06-06 16:22:53 +08:00
zmstone 69caf4b4eb docs: add changelog for PR 13180 2024-06-06 09:35:51 +02:00
zmstone 2525bd0c16 perf: eliminate the loop-back fake async inet_reply message
Now that EMQX is on OTP 26 by default, the fake inet_reply
message when the send call returns ok only adds overhead.

For TCP (gen_tcp module), OTP 26 no longer supports direct port_command
so we had to swith to gen_tcp:send, then fake an async reply:
see https://github.com/emqx/esockd/pull/181

For TLS (ssl module), it has never supported async send anyway.

This commit switches to call Transport:send/2 directly,
this should result in one less loop-back message for each message.

For OTP 25 on which EMQX can still be compiled, one will have to
suffer the performance penalty for gen_tcp:send function to
do a non-optimized 'receive' for the send result.
2024-06-06 09:35:51 +02:00
zmstone 5c3f5d8085 perf: do not call inet getstat before each and every send
In a stress test environment, when alarm is enabled, there were
a lot of long_schedule warnings with the stacktrace pointing to
congestion alarm based inet:getstat function.
When alarm is disabled, the one single client is able to
hold 40,000 QoS 1 messages per second (inflight=32) throughput.
When alarm is enabled, its mqueue overflows.

This commit removes the call before each and every data send,
so to rely on emit_stats timer to trigger the congestion check.
2024-06-06 09:35:51 +02:00
zmstone 257435799d
Merge pull request #13191 from zmstone/0605-otp26-for-docker-images
ci: OTP 26 (26.2.5-1) for docker images
2024-06-06 08:07:03 +02:00
firest d4118c6e8e fix: fix typos 2024-06-06 11:19:40 +08:00
JimMoen dff31b293c
perf(utils_sql): pre-build regexp 2024-06-06 11:01:38 +08:00
zmstone c41be7ee22 chore: fix dialyzer warning 2024-06-05 23:37:21 +02:00
zmstone 07a3fbaf1a docs: add changelog for PR 13190 2024-06-05 23:28:41 +02:00
zmstone 1af06e4533
Merge pull request #13190 from zmstone/0605-stop-release-el7-and-ubuntu18
ci: stop releasing on centos7 (el7) and ubuntu18
2024-06-05 23:25:37 +02:00
Ilia Averianov dc2e6d1695
Merge pull request #13163 from savonarola/0523-ds-shared-subs-dispatch
Inject shared subcription handling into durable session
2024-06-05 23:59:50 +03:00
zmstone c7f585cc21 fix(bin/emqx): ensure -noinput is prior to -noshell
iex seems to depend on this order, otherwise it terminiates right
after boot
2024-06-05 21:55:39 +02:00
SergeTupchiy 64862b296c
Merge pull request #13179 from SergeTupchiy/dashboard-swagger-apply-body-validator
feat(emqx_dashboard_swagger): apply field validator in request body check
2024-06-05 21:25:07 +03:00
Serge Tupchii 159da912c2 feat(emqx_dashboard_swagger): apply field validator in request body check 2024-06-05 19:35:04 +03:00
JimMoen 6bf3492eb4
docs: add changelog for pr 13189 2024-06-06 00:30:19 +08:00
JimMoen 144264e0d8
test: add utils_sql test cases 2024-06-06 00:30:18 +08:00
JimMoen 627b8c45d2
fix(utils_sql): improve insert sql regular expression 2024-06-06 00:30:17 +08:00
Ilya Averyanov b075b7120c feat(sessds): implement dispatchig between CE/EE shared sub agents 2024-06-05 19:17:58 +03:00
Ilya Averyanov 60556abc4f fix(dashboard_monitor): correctly merge old and new sample data 2024-06-05 18:49:52 +03:00
Kjell Winblad 2956e849eb fix(pgsql connector): better msg when failing to remove statement 2024-06-05 16:58:14 +02:00
Ivan Dyachkov e1e5dc231d build: use generic env variables for otp and elixir when building docker image 2024-06-05 16:34:23 +02:00
zmstone 9e3c817e5b ci: OTP 26 (26.2.5-1) for docker images 2024-06-05 16:18:55 +02:00
Kjell Winblad 336089f8a7 fix: bug found by dialyzer and make test case cleaner 2024-06-05 15:53:02 +02:00
Thales Macedo Garitezi ae0379f974
Merge pull request #13181 from thalesmg/force-stop-connector-r57-20240604
fix(resource manager): force kill process if stuck when stopping/removing
2024-06-05 09:08:30 -03:00
zmstone cf0eefee54 ci: stop releasing on centos7 (el7) and ubuntu18 2024-06-05 14:02:06 +02:00
lafirest d79193fde4
Merge pull request #13177 from lafirest/sync-authn-com
feat: sync `client.check_authn_complete` to release-57
2024-06-05 19:51:10 +08:00
JimMoen f0721bdb97
Merge pull request #13176 from JimMoen/erlfmt-file-name-by-find
build: run erlfmt with files name by `$(FIND)`
2024-06-05 17:41:19 +08:00
JimMoen 0eac19ef12
style: disable elvis `param_pattern_matching` check 2024-06-05 10:48:34 +08:00
JimMoen 51e55dcad8
style: track reformat commit in git-blame-ignore-revs 2024-06-05 10:48:33 +08:00
JimMoen 336ed1b922
style: reformat files in `erlang-mode` 2024-06-05 10:29:44 +08:00
JimMoen 023bb5e766
build: run erlfmt with files name by `$(FIND)` 2024-06-05 10:29:43 +08:00
Thales Macedo Garitezi 5eab221f7c
Merge pull request #13175 from thalesmg/disable-prepared-statements-postgres-r57-20240603
feat(postgres): add `disable_prepared_statements` option
2024-06-04 12:29:53 -03:00
Thales Macedo Garitezi f17aefe3d7 fix(action/source api): improve returned error message on timeout 2024-06-04 12:04:55 -03:00
zmstone 3d992e4501
Merge pull request #13171 from zmstone/0603-improve-compatibility-check
chore: improve emqx boot script's compatibility check
2024-06-04 16:58:18 +02:00
zmstone cda6d5f636
Merge pull request #13172 from zmstone/0603-add-redis-arg-formatter-to-rule-engine-funcs
feat(redis): add a rule function to help formatting redis args
2024-06-04 16:56:14 +02:00
Thales Macedo Garitezi 3013189cd7 fix(resource manager): force kill process if stuck when stopping/removing
Fixes https://emqx.atlassian.net/browse/EMQX-12357
2024-06-04 11:38:24 -03:00
Ilya Averyanov 9cdfbb0845 feat(sessds): make ds session be aware of shared subscriptions 2024-06-04 17:15:30 +03:00
Thales Macedo Garitezi c07bc68e6f feat(postgres): add `disable_prepared_statements` option
Fixes https://emqx.atlassian.net/browse/EMQX-12496

Some Postgres connections, such ones made to [PGBouncer](https://www.pgbouncer.org/) or
[Supabase in Transaction Mode](https://supabase.com/), do not support some session
features like prepared statements.
2024-06-04 10:11:25 -03:00
zmstone 8276ae54a1 chore: improve emqx boot script's compatibility check
Prior to this change, the command used to check installation
and os compatibility is done by starting a 'erl' process using
default flags. it might be unnecessarily expensive in large
VM instances.
In this change, we have added small enough +S +P and +Q number to
make lower the cost.
2024-06-04 12:11:43 +02:00
firest 87384cae32 fix(events): call `client.check_authn_complete` even if authentication fails 2024-06-04 17:55:39 +08:00
firest 92d26ff27b chore: update change 2024-06-04 17:55:30 +08:00
firest e4e53844d5 feat(events): add new hook && event `client.check_authn_complete` 2024-06-04 17:55:21 +08:00
Ilia Averianov dc95218c68
Merge pull request #13144 from savonarola/0528-increase-bridge-buffer-drop-log-level
chore(bridges): increase log level for bridge buffer overflow reports
2024-06-04 12:37:50 +03:00
Kjell Winblad 572ca6433e fix(pgsql connector): improvements due to suggestions from @thalesmg
Co-authored-by: Thales Macedo Garitezi <thalesmg@gmail.com>
2024-06-04 10:11:45 +02:00
zhongwencool a8a67a2ac9
Merge pull request #13151 from zhongwencool/authz-trace-log
chore: make authz's logs easier to understand
2024-06-04 11:12:09 +08:00
JimMoen 93d5e77698
Merge pull request #13145 from JimMoen/fix-plugin-app-priv-path 2024-06-04 09:17:48 +08:00
zmstone e3596ad836
Merge pull request #13170 from Kinplemelon/kinple/for-upgrade-dashboard
chore(dashboard): bump dashboard version to v1.9.1-beta.1 & e1.7.1-beta.1
2024-06-03 23:58:11 +02:00
zmstone e7fecd5e91 docs: add changelog for PR 13172 2024-06-03 23:13:13 +02:00
zmstone aa7ce1f641 fix(bridge/redis): add test case for map_to_redis_hset_args 2024-06-03 23:05:43 +02:00
Kjell Winblad f2ccfff803 fix(pgsql connector): handle prepared statement already exists
In a user's log file it was found that that the pgsql driver can end up
in a situation where the prepared statement for a channel/action is not
properly removed before a channel with the same name as the prepared
statement is added to the connector. This commit handles this by
attempting to remove the old prepared statement if one already exists
when adding channel.

Related issue:
https://emqx.atlassian.net/browse/EEC-1036
2024-06-03 16:14:26 +02:00
zmstone e3ed7b59dd feat(redis): add a rule function to help formatting redis args
The new function named 'map_to_redis_hset_args' can be used to format
a map's key-value pairs into redis HSET (or HMSET) arg list.

This new function is dedicated for redis to avoid abuse for other
data integrations.
2024-06-03 14:09:15 +02:00
Thales Macedo Garitezi c5547543e0
Merge pull request #13069 from thalesmg/azure-blob-storage-action-m-20240508
feat: implement azure blob storage action
2024-06-03 08:56:37 -03:00
Ilia Averianov 193978af90
Merge pull request #13168 from savonarola/0530-fix-mgmt-test
chore(tests): improve test stability
2024-06-03 14:44:12 +03:00
zhongwencool fda365a87b chore: make authz's logs easier to understand 2024-06-03 18:01:57 +08:00
Kinplemelon 95c23fb3ad chore(dashboard): bump dashboard version to v1.9.1-beta.1 & e1.7.1-beta.1 2024-06-03 17:31:23 +08:00
JimMoen 21624bc865
fix: get plugin app vsn from field `rel_apps` 2024-06-03 15:26:14 +08:00
zmstone b6ff67d712
Merge pull request #13093 from zmstone/0522-upgrade-to-brod-3.18
chore: upgrade to brod 3.18.0
2024-06-02 15:06:40 +02:00
JimMoen 8d22a5a3ae
Merge pull request #13167 from JimMoen/fix-rule-events-i18n-todo
fix: missing rule event i18n in zh_cn
2024-06-02 18:23:20 +08:00
zmstone 8d7417d51c chore: stop pinning supervisor in mix.exs 2024-06-02 10:10:17 +02:00
zmstone 9637b14543 fix: upgrade to brod 3.18.0 to fix unnecessary rebalance 2024-06-01 10:57:24 +02:00
zmstone ec7ec7261e
Merge pull request #13155 from zmstone/0529-hide-enable-flag-which-has-default-value-true
refactor: hide 'enable' config from example when it's 'true' by default
2024-05-31 21:52:40 +02:00
zmstone 12fd1f6a48
Merge pull request #13080 from zmstone/0521-default-retry_interval-to-infinity
change `mqtt.retry_interval` default value to `infinity`
2024-05-31 21:36:38 +02:00
Ilya Averyanov 57741a41e9 chore(tests): improve test stability 2024-05-31 22:27:31 +03:00
zmstone fb07f40bea test: fix default value of retry_interval in test case 2024-05-31 17:53:12 +02:00
zmstone 20c92407c7 feat: change message retry_interval default value to infinity
Previous Setting: The default value for `retry_interval` was 30 seconds.

New Default: The default `retry_interval` has been changed to 'infinity'.
With this update, EMQX will not automatically retry message deliveries
by default.

Compliance and Compatibility: Aligning with MQTT specification
standards, in-session message delivery retries are not typically
compliant. We recognize that some users depend on this feature, so the
option to configure retries remains available for backward
compatibility.
2024-05-31 17:53:12 +02:00
zmstone 37ce8d93a1
Merge pull request #13164 from zmstone/0530-http-acl-compatibility-with-v4
0530 http acl compatibility with v4
2024-05-31 16:28:30 +02:00
Thales Macedo Garitezi efa4432eef docs: fix docs 2024-05-31 11:10:24 -03:00
Thales Macedo Garitezi 347971e24a fix: check `max_block_size` for direct transfers 2024-05-31 11:07:44 -03:00
Thales Macedo Garitezi 4859cebd9f refactor: move `min_block_size` one level up 2024-05-31 11:07:44 -03:00
Thales Macedo Garitezi 9a1d3ea04f chore: bump app vsns 2024-05-31 11:07:44 -03:00
Thales Macedo Garitezi 616f14ae53 fix: avoid uploading blocks too frequently and splitting large buffers
Fixes https://github.com/emqx/emqx/pull/13069#discussion_r1613706747
2024-05-31 11:07:44 -03:00
Thales Macedo Garitezi af99829a21 refactor: move common templating logic to `emqx_connector_aggreg_buffer_ctx` 2024-05-31 11:07:44 -03:00
Thales Macedo Garitezi c916c83c7c feat: implement azure blob storage action
Fixes https://emqx.atlassian.net/browse/EMQX-12280
2024-05-31 11:07:44 -03:00
Thales Macedo Garitezi 60d24c6ad5 refactor: simplify resource_opts definition 2024-05-31 11:07:44 -03:00
Thales Macedo Garitezi 729441d1ce refactor(connector aggregator): move shared schemas to app 2024-05-31 11:07:44 -03:00
Ilya Averyanov db713cb656 chore(bridges): increase log level for bridge buffer overflow reports
Co-authored-by: Andrew Mayorov <encube.ul@gmail.com>
2024-05-31 16:35:18 +03:00
Thales Macedo Garitezi c289c7d065
Merge pull request #13148 from thalesmg/EMQX-12251-fix-conn-api-timeout-case-clause-r571-20240528
fix(connector api): handle `timeout` when waiting for connector status
2024-05-31 10:07:35 -03:00
zmstone 6fe8a09e97 fix(authz/http): rename PH_ACCESS to VAR_ACCESS 2024-05-31 14:49:54 +02:00
zmstone b457c2a49c refactor: hide 'enable' config from doc when it's 'true' by default 2024-05-31 14:10:03 +02:00
JimMoen 45e2c81ebc
fix: missing rule event i18n in zh_cn 2024-05-31 17:51:47 +08:00
Ivan Dyachkov b232784df2
Merge pull request #13165 from id/0531-sync-release-57
sync release 57
2024-05-31 09:15:50 +02:00
Ivan Dyachkov 29ad07ce29 Merge remote-tracking branch 'upstream/release-57' into 0531-sync-release-57 2024-05-31 07:32:26 +02:00
Ivan Dyachkov b14a138bf1
Merge pull request #13154 from id/emqx-12190-fix-apt-purge
fix(deb): fix apt purge when emqx service was still running
2024-05-31 07:26:24 +02:00
zmstone f681126f4d docs: add changelog for PR 13164 2024-05-30 22:38:56 +02:00
zmstone ca32cf8d29 Merge branch 'emqx-12487-fix-authz-http-content-type' into 0530-http-acl-compatibility-with-v4 2024-05-30 22:30:20 +02:00
zmstone e381696c55
Merge pull request #13079 from zmstone/0521-handle-kafka-message_too_large-error
chore: upgrade kafka producer lib wolff to 1.10.4 handle `message_too_large`
2024-05-30 21:11:10 +02:00
Ivan Dyachkov a22f633f60
Merge pull request #13153 from id/emqx-12467-always-notify-emqx.io-on-releases
ci: always trigger package reindex by emqx.io on releases
2024-05-30 18:30:34 +02:00
Ivan Dyachkov 2d5d96ae33 ci(ui-tests): retry getting element by xpath 2024-05-30 18:27:29 +02:00
Ivan Dyachkov 830926044c chore: bump erlang-rocksdb to 1.8.0-emqx-5
- fix macos build https://github.com/google/snappy/issues/183
- pre-built binaries for latest platforms
2024-05-30 17:13:06 +02:00
Ivan Dyachkov e54395f501 ci: always trigger package reindex by emqx.io on releases 2024-05-30 17:04:47 +02:00
Ivan Dyachkov 38f49de6d9 fix(deb): fix apt purge when emqx service was still running 2024-05-30 17:03:13 +02:00
zmstone a00d9f17b1 chore: upgrade kafka producer lib wolff to 1.10.4
wolff-1.10.4 handles message_too_large error code from Kafka.
It tries to split the too-large batch into single-call batches
(for EMQX, one call batch is always one message), and retry.
In case a single-call batch is too large, EMQX should increment
a failure counter.
2024-05-30 15:40:10 +02:00
zmstone 460081a22e
Merge pull request #13131 from zmstone/0527-handle-unicode-in-template-strings
0527 handle unicode in template strings
2024-05-30 15:37:43 +02:00
Ilya Averyanov 97f9c81e19 feat(auth): add legacy ${access} placeholder 2024-05-30 15:47:48 +03:00
Ivan Dyachkov 0c4da98b52 chore: update deps 2024-05-30 11:53:00 +02:00
Ivan Dyachkov 1129c18330 fix(authz_http): fix content-type header in http request 2024-05-30 11:36:13 +02:00
zhongwencool 8ab7e75e64
Merge pull request #13139 from zhongwencool/influxdb-client-failed-msg-port
chore: improved InfluxDB connection error messaging
2024-05-30 10:57:21 +08:00
zmstone 532812f6f6 test: assert results 2024-05-29 22:10:34 +02:00
zmstone 9fe29bf5f7 chore: bump kafka bridge app vsn 2024-05-29 21:57:14 +02:00
zmstone 78a6100346 chore: fix app vsn bumps
only bug fixes so far
2024-05-29 21:56:22 +02:00
zmstone 1db9d54d17 fix: handle unicode in data integration template strings
The bug was introduced in 5.7.0 (#12893)
2024-05-29 21:53:07 +02:00
zmstone c54d25de98
Merge pull request #13070 from zmstone/0518-improve-kafka-connection-error-logs
0518 improve kafka connection error logs
2024-05-29 16:24:01 +02:00
Kjell Winblad 5017ef82a3
Merge pull request #13130 from kjellwinblad/kjell/fix_redis_trace_format/EMQX-12428
fix(redis trace): add separators in redis batch action trace
2024-05-29 15:59:32 +02:00
Kjell Winblad 6810591911
Merge pull request #13147 from kjellwinblad/kjell/fix_function_clause_when_decoding_protobuf/EMQX-12453
fix: make protobuf schema decode error reported to user less cryptic
2024-05-29 15:56:27 +02:00
Kjell Winblad 3769bbb7f4
Merge pull request #13140 from kjellwinblad/kjell/republish_trace_crash/EMQX-12474
fix: trace formatter should not crash when given a non-binary payload
2024-05-29 15:54:02 +02:00
Kjell Winblad 9b089a4e5a fix: use explain instead of msg as error explanation and add test 2024-05-29 10:20:15 +02:00
Kjell Winblad 479889f162
Merge pull request #13136 from kjellwinblad/kjell/fix_oracle_trace_format/EMQX-12433
fix(oracle action trace): parameters should not be rendered as IO Data
2024-05-29 09:12:38 +02:00
zmstone a4ec9d7cb0
Merge pull request #13133 from zmstone/0527-port-back-diverged-modules
chore: port diverged modules back to oss
2024-05-29 09:03:30 +02:00
zhongwencool 7d9333a9d7 chore: bump influxdb app version 2024-05-29 11:13:17 +08:00
zhongwencool 00d74826ec chore: improved InfluxDB connection error messaging 2024-05-29 11:13:17 +08:00
Thales Macedo Garitezi 802361dbd0 fix(connector api): handle `timeout` when waiting for connector status
Fixes https://emqx.atlassian.net/browse/EMQX-12251
2024-05-28 14:19:32 -03:00
Kjell Winblad 9d7acc6a32 docs: add change log entry 2024-05-28 18:24:45 +02:00
Kjell Winblad 82800faadf fix: make protobuf schema decode error reported to user less cryptic
Before this commit the user would see a cryptic warning log including
function_clause when decoding a message failed. This commit improves
this by removing function_caluse as well as some other cryptic words
from the message and adding a description describing what went wrong.

Fixes:
https://emqx.atlassian.net/browse/EMQX-12453
2024-05-28 18:07:14 +02:00
Kjell Winblad 3151a3123e chore: bump version of emqx_redis_bridge app 2024-05-28 17:23:35 +02:00
Kjell Winblad 3f1fe413ee refactor: simplify redis trace formatting 2024-05-28 17:22:58 +02:00
Kjell Winblad 4099e22a77 docs: add changelog entry 2024-05-28 17:22:58 +02:00
Kjell Winblad cbdde7165e fix(redis trace): add separators in redis batch action trace
Logger will transform data that looks like IO data into a string which
made redis batch traces look like the spaces had been removed
from the strings. To prevent this, we render the batched commands into
binary string separated by spaces and semicolon. The components of a
single command is separated by spaces and the commands in a batch are
separated by semicolons.

Fixes:
https://emqx.atlassian.net/browse/EMQX-12428
2024-05-28 17:22:58 +02:00
Kjell Winblad 5e3de1a4e3 fix(emqx_logger_jsonfmt:best_effort_json_test): test cases 2024-05-28 17:15:32 +02:00
zmstone 062ab31ecf Merge remote-tracking branch 'origin/release-57' into 0527-port-back-diverged-modules 2024-05-28 14:35:25 +02:00
zmstone 40080f5e7d
Merge pull request #13141 from zmstone/0528-test-fix-dashboard-config-test-with-stable-base-config
test: fix test case to have deterministic base config
2024-05-28 14:32:55 +02:00
Andrew Mayorov 9ae4de10ed
Merge pull request #13127 from keynslug/fix/EMQX-12439/update-leaner-error
fix(bridge-v2): report descriptive error on invalid update request
2024-05-28 13:11:41 +03:00
zmstone e9cc88cb95 test: fix test case to have deterministic base config 2024-05-28 12:03:01 +02:00
Kjell Winblad 2eb5c24068 docs: add change log entry 2024-05-28 11:13:57 +02:00
Kjell Winblad 84bc6ba28c fix: trace formatter should not crash when given a non-binary payload
Fixes:
https://emqx.atlassian.net/browse/EMQX-12474
2024-05-28 11:13:51 +02:00
Kjell Winblad e3cb63f59a docs: add change log entry 2024-05-28 11:08:07 +02:00
Kjell Winblad e55bda6fe6 chore: bump app versions
Bump app version as required to pass the check which is done by the
following script:

./scripts/apps-version-check.sh
2024-05-28 11:01:00 +02:00
Kjell Winblad f65168982b fix(oracle action trace): parameters should not be rendered as IO Data
This forces the parameters to the database statement to be rendered as
a JSON array in JSON traces instead of being rendered as a string when
the parameters are interpreted as IO data.

Fixes:
https://emqx.atlassian.net/browse/EMQX-12433
2024-05-28 10:59:44 +02:00
zmstone 8f2ca71d8b test: fix test case to have deterministic base config 2024-05-28 10:57:20 +02:00
Andrew Mayorov c04aaad0a4
chore(bridge-v2): leave comment describing need for `nowarn_function` 2024-05-28 10:31:14 +02:00
ieQu1 02d10a2023
Merge pull request #13135 from ieQu1/dev/refactor-sessds2
Refactor session DS code. No functional change.
2024-05-28 10:24:15 +02:00
zmstone e4abd8fca6 Merge remote-tracking branch 'origin/release-57' into 0527-port-back-diverged-modules 2024-05-28 09:50:59 +02:00
ieQu1 8fbeca4321
chore: Version bumps 2024-05-28 00:14:01 +02:00
ieQu1 04305d004f
refactor(sessds): Extract metadata keys to a header 2024-05-27 23:36:20 +02:00
ieQu1 16d1425982
refactor(emqx): Move files related to durable session to a subdir 2024-05-27 23:31:15 +02:00
zmstone 1148091f0b chore: restore test code 2024-05-27 23:05:21 +02:00
zmstone 96ef37d0ea chore: port diverged modules back to oss 2024-05-27 22:40:08 +02:00
zmstone e552b81ade ci: run apps/emqx tests in 8 groups 2024-05-27 20:59:50 +02:00
zmstone 2771a10d39 test: fix a flaky one 2024-05-27 20:59:50 +02:00
zmstone 5050ddb174 chore: handle ctl command return 'true' 2024-05-27 20:59:50 +02:00
zmstone 238c207b09 chore: bump app versions 2024-05-27 20:26:52 +02:00
zmstone 41cbfcfaa1 Merge remote-tracking branch 'origin/release-57' into 0527-sync-5.7.0-to-master 2024-05-27 20:10:44 +02:00
Andrew Mayorov 663f4fd39f
chore: bump application versions 2024-05-27 17:49:16 +02:00
Andrew Mayorov 08d88ea814
feat(bridge-api): improve error messages for Update Source API 2024-05-27 17:49:16 +02:00
Andrew Mayorov ed7c29ec26
fix(api): mention spec override in "request metadata" type 2024-05-27 16:57:45 +02:00
Ivan Dyachkov d885ac3dd8
Merge pull request #13129 from id/0527-cut-5.7.0
release 5.7.0
2024-05-27 15:48:30 +02:00
Andrew Mayorov 5c2a68076f
fix(bridge-v2): report descriptive error on invalid update request
Before this commit, generic validation errors were reported as union
mismatches of _all_ of the bridge schemas. After this commit, specific
schema is chosen before validation.
2024-05-27 14:37:10 +02:00
Ivan Dyachkov f393fd5304 chore: release 5.7.0 2024-05-27 14:32:23 +02:00
zmstone b2f5e50f16
Merge pull request #13120 from ieQu1/dev/ds-api-site-status
fix(dsapi): Check status of the node via Mria
2024-05-25 05:42:05 +02:00
zmstone 4e07437e80 ci: delete dos2unix 2024-05-24 23:22:15 +02:00
zmstone 0763e29786 chore: prepare for 5.7.0-rc.2 release 2024-05-24 21:10:37 +02:00
ieQu1 73df01e934
fix(dsapi): Check status of the node via Mria 2024-05-24 20:59:07 +02:00
ieQu1 7f356aa3a8
Merge pull request #13115 from ieQu1/dev/fix-drop-generations2
Mitigate transient errors when dropping generations
2024-05-24 20:13:39 +02:00
Ilia Averianov b0e1fa9474
Merge pull request #13118 from savonarola/0524-fix-proc-template-perf
perf(emqx_placeholder): do not try to decode maps as json
2024-05-24 21:13:20 +03:00
ieQu1 830b62d899
fix(dsrepl): Retry sending ra commands to the leader 2024-05-24 19:09:34 +02:00
ieQu1 1ffc7d5d9e
fix(dsrepl): Treat all exceptions from storage layer as recoverable 2024-05-24 19:09:34 +02:00
ieQu1 25721bceba
fix(dsstor): Delete generation metadata before dropping it 2024-05-24 19:09:33 +02:00
ieQu1 3d9837a0b8
test(ds): Add emqx_ds_replication_SUITE:t_drop_generation 2024-05-24 19:09:33 +02:00
Ilya Averyanov 327080e70e perf(emqx_placeholder): do not try to decode maps as json
fix
2024-05-24 20:08:31 +03:00
Andrew Mayorov 2908da4a8a
Merge pull request #13116 from keynslug/fix/sessds/monitor-api-metrics
fix(monitor): reflect durable subscriptions in historical metrics
2024-05-24 16:54:48 +03:00
Andrew Mayorov c30b881239
test(monitor): verify historical and current metrics are consistent 2024-05-24 14:56:10 +02:00
Andrew Mayorov fd9655bc35
fix(monitor): unify metric names for consistency and simplicity 2024-05-24 14:55:48 +02:00
Andrew Mayorov 7b137c0aaf
fix(monitor): reflect durable subscriptions in historical metrics
Essentially in the same manner as they are currently reflected in the
current metrics.
2024-05-24 14:08:35 +02:00
JianBo He 9091b8378e
Merge pull request #13113 from Kinplemelon/kinple/for-upgrade-dashboard
chore(dashboard): bump dashboard version to v1.9.0 & e1.7.0
2024-05-24 18:27:41 +08:00
Kinplemelon 6f937a8817 chore(dashboard): bump dashboard version to v1.9.0 & e1.7.0 2024-05-24 17:00:08 +08:00
zmstone 6ec8ae5a5f
Merge pull request #13112 from HJianBo/change-the-default-batch-size-s3-uploader
Fix(s3): change the batch_size to 1 for direct mode
2024-05-24 10:56:53 +02:00
Andrew Mayorov 29d203ae33
Merge pull request #13108 from keynslug/fix/ct-flaky/mgmt
test(mgmt): avoid inter-suite contamination by switching to cth tooling
2024-05-24 11:14:16 +03:00
JianBo He 9a64b95a53 chore: update dashboard version 2024-05-24 16:02:11 +08:00
JianBo He adaf238131 fix(s3): fix the convert function if the mode is missing 2024-05-24 16:02:06 +08:00
zhongwencool e5da4aa128
Merge pull request #13078 from zhongwencool/http-415
feat: return 415 when UNSUPPORTED_MEDIA_TYPE
2024-05-24 15:59:05 +08:00
JianBo He 1899cf2daf
Merge pull request #13111 from JimMoen/fix-plugin-install-badmatch
fix: match decode plugin config map failed case
2024-05-24 15:23:30 +08:00
JimMoen 5b60f6a5b2
fix: make dialyzer happy 2024-05-24 14:29:02 +08:00
JimMoen 6798a26ecb
chore: bump dashboard tag to e1.7.0-beta.11 2024-05-24 13:51:57 +08:00
JimMoen 43506495ae
fix: ensure plugin configured states after join cluster 2024-05-24 13:51:56 +08:00
JimMoen 874bcd9a8b
fix: match decode plugin config map failed case 2024-05-24 10:20:50 +08:00
zhongwencool 3aa1f86d9e chore: is_content_type_json to validate_content_type_json 2024-05-24 10:13:24 +08:00
zhongwencool c013366b27 chore: upgrade minirest to 1.4.1 to ignore 415 code check 2024-05-24 10:13:23 +08:00
zhongwencool 5c759941d5 feat: return 415 when UNSUPPORTED_MEDIA_TYPE 2024-05-24 10:13:23 +08:00
zmstone 3265a5f9b0
Merge pull request #13110 from zmstone/0523-prepare-for-release-5.7.0-rc.1
chore: prepare for release cut 5.7.0-rc.1
2024-05-23 22:24:07 +02:00
zmstone 63721bf1db
Merge pull request #13109 from ieQu1/dev/sync-release-57-240523
Sync release-57 240523
2024-05-23 21:54:12 +02:00
zmstone c3c6da7ec4 chore: prepare for release cut 5.7.0-rc.1 2024-05-23 21:39:15 +02:00
Zaiming (Stone) Shi 3a4b8e6c24
Merge pull request #13106 from zmstone/0523-add-customer-type
0523 add customer type (4=BYOC) to license schema
2024-05-23 21:30:02 +02:00
Zaiming (Stone) Shi 40288b99b2
Merge pull request #13101 from JimMoen/fix-plugin-config-map
fix: allow put plugin config without schema
2024-05-23 21:18:43 +02:00
ieQu1 c952e46f08
Merge remote-tracking branch 'origin/release-57' 2024-05-23 21:04:03 +02:00
Thales Macedo Garitezi 823a6bc521
Merge pull request #13107 from thalesmg/hide-clientv2-response-type-r57-20240523
fix(client mgmt api): hide unused return type
2024-05-23 16:03:51 -03:00
Andrew Mayorov 7878d106f6
test(mgmt): avoid inter-suite contamination by switching to cth tooling 2024-05-23 20:17:34 +02:00
Andrew Mayorov b4c6968f8c
Merge pull request #13104 from keynslug/fix/EMQX-12415/last-resort-poll
fix(dsrepl): trigger "last-resort" pending transitions handler when idle
2024-05-23 21:17:03 +03:00
ieQu1 0dc507441a
Merge pull request #13105 from ieQu1/dev/sessds-renew-streams-interval
fix(sessds): Change the defaults to renew streams every 1 second
2024-05-23 18:23:20 +02:00
Thales Macedo Garitezi b1e3c941fb fix(client mgmt api): hide unused return type
Fixes https://emqx.atlassian.net/browse/EMQX-12427
2024-05-23 13:17:43 -03:00
Andrew Mayorov d47bf8076a
test(mgmt): better isolate testsuite running environments 2024-05-23 17:53:13 +02:00
zmstone d13737ab6c chore: make it easier to override default profile 2024-05-23 17:30:06 +02:00
zmstone c737045dff chore: add customer type 4 (BYOC) 2024-05-23 17:30:06 +02:00
ieQu1 5584b658c9
fix(sessds): Change the defaults to renew streams every 1 second 2024-05-23 17:17:29 +02:00
Zaiming (Stone) Shi 1d99ba2a8a
Merge pull request #13102 from JimMoen/fix-ds-prom-badkey
fix: add ds metrics into prometheus zipper init acc
2024-05-23 16:57:06 +02:00
Thales Macedo Garitezi 118c1d2806
Merge pull request #13103 from thalesmg/fix-another-ds-counter-nit-r57-20240523
fix(monitor api): fix cluster metric aggregation
2024-05-23 10:57:53 -03:00
William Yang bb3f858db2
Merge pull request #13086 from qzhuyan/dev/william/quic-lb
feat: quic-lb support
2024-05-23 15:31:14 +02:00
Andrew Mayorov ba6382adae
fix(dsrepl): trigger "last-resort" pending transitions handler when idle
This is a hack to work around the unintended issues causing shard
allocator to become idle even when there are pending transitions.
2024-05-23 14:54:01 +02:00
Andrew Mayorov 839b143fc4
fix(sessds): consider message durability disabled by default 2024-05-23 14:48:39 +02:00
Thales Macedo Garitezi c0e3a81c61 fix(monitor api): fix cluster metric aggregation
Fixes https://emqx.atlassian.net/browse/EMQX-12423
Fixes https://emqx.atlassian.net/browse/EMQX-12267
2024-05-23 09:38:24 -03:00
Andrew Mayorov bf326acd7b
fix(dsrepl): handle stopping non-yet-running shard supervisor 2024-05-23 14:34:27 +02:00
Kjell Winblad 0e5b02c373
Merge pull request #13100 from kjellwinblad/kjell/s3_aggregate_only_has_result_trace/EMQX-12429
fix: add action rendered trace for s3 in aggregated mode
2024-05-23 14:29:18 +02:00
JimMoen a40c7d646a
fix: apply suggestions from code review, thanks @zmstone 2024-05-23 20:28:14 +08:00
JimMoen b91ecac168
refactor(prom): unify function name to avoid multiple levels call 2024-05-23 20:11:22 +08:00
JimMoen 065411c69c
fix: add ds metrics into prometheus zipper init acc 2024-05-23 20:11:21 +08:00
Zaiming (Stone) Shi 147d7f5d11
Merge pull request #13098 from zmstone/0523-more-ct-chunks-for-emqx-app
ci: run apps/emqx tests in 8 groups
2024-05-23 14:04:03 +02:00
Kjell Winblad 89b47e8ffc fix(s3 tracing): do not format records as IO data in aggregate mode 2024-05-23 12:41:30 +02:00
Kjell Winblad fb7688ab94 fix(trace): make sure that the payload encode works with nested payloads
This commit makes sure that the trace setting for payload encode works
even when the payload is in a nested structure or when the payload key
is a binary instead of an atom.

Fixes:
https://emqx.atlassian.net/browse/EMQX-12424
2024-05-23 12:30:56 +02:00
JimMoen 5dc96a37e2
fix: ensure plugin avsc serde before config 2024-05-23 17:46:58 +08:00
JimMoen 25a9aa1797
fix: allow put plugin config without schema 2024-05-23 17:33:34 +08:00
JimMoen 99869821fb
fix: ensure plugin config map after fresh install 2024-05-23 17:16:16 +08:00
William Yang 94e59c8fa7 feat(quic-lb): fix test 2024-05-23 10:32:23 +02:00
William Yang d8eecfe64f feat(quic-lb): add configuration 2024-05-23 10:32:20 +02:00
Kjell Winblad e10c87b825 fix: add action rendered trace for s3 in aggregated mode
Fixes:
https://emqx.atlassian.net/browse/EMQX-12429
2024-05-23 10:25:27 +02:00
Andrew Mayorov 398dc97ed6
Merge pull request #13092 from keynslug/fix/dsrepl/site-autoleave
fix(dsrepl): properly handle transaction abort during forget site
2024-05-23 10:56:23 +03:00
ieQu1 950fa82be3
Merge pull request #13097 from ieQu1/dev/ds-replay-unrecoverable-no-test
feat(sessds): Handle unrecoverable errors
2024-05-23 09:49:21 +02:00
William Yang 34a69625b5 feat: quic-lb support 2024-05-23 09:17:09 +02:00
Kjell Winblad 26c988fe11
Merge pull request #13077 from kjellwinblad/kjell/fix_action_update_race_issue/EMQX-12376
fix: action config update would sometimes not be reflected in connector
2024-05-23 09:11:48 +02:00
Andrew Mayorov 2f6729d203
Merge pull request #13089 from keynslug/fix/EMQX-12437/restore
fix(s3-bridge): restore backward config compatibility
2024-05-23 10:10:01 +03:00
zmstone 1d5f3d7a36 chore: handle ctl command return 'true' 2024-05-23 08:58:31 +02:00
zmstone b0832ecc74 test: fix a flaky one 2024-05-23 08:55:28 +02:00
JianBo He 4053356597
Merge pull request #13063 from JimMoen/improve-plugin-config-behavior
fix(plugin): serde not found on new-joined nodes
2024-05-23 11:24:44 +08:00
lafirest b1076221b0
Merge pull request #13085 from lafirest/fix/rocket_namespace
fix(rocketmq): fix namespace error for RocketMQ
2024-05-23 10:39:30 +08:00
zmstone 63c34a4c40 ci: run apps/emqx tests in 8 groups 2024-05-22 23:45:54 +02:00
Thales Macedo Garitezi 625fcd5821
Merge pull request #13096 from thalesmg/test-fix-broken-m-20240522
test: fix broken test
2024-05-22 17:56:36 -03:00
ieQu1 07774ab060
feat(sessds): Handle unrecoverable errors 2024-05-22 22:45:37 +02:00
Zaiming (Stone) Shi 8d1abe8766
Merge pull request #13088 from zmstone/0522-chore-update-dashboard-vsn
chore: update dashboard version
2024-05-22 22:04:25 +02:00
Thales Macedo Garitezi 63cb12d7c2
Merge pull request #13095 from thalesmg/fix-monitor-ds-counters-again-r57-20240522
fix(monitor api): add ds connections and subscriptions to old counters
2024-05-22 16:43:15 -03:00
Thales Macedo Garitezi 20a767eee8 test: fix broken test 2024-05-22 16:19:47 -03:00
Zaiming (Stone) Shi aa86772f96
Merge pull request #13094 from zmstone/0522-sync-release-57-to-master
0522 sync release 57 to master
2024-05-22 21:13:31 +02:00
ieQu1 bfd01c425d
Merge pull request #13072 from ieQu1/dev/fix-drop-generation
Idempotent drop_generation
2024-05-22 21:13:30 +02:00
ieQu1 6eb04f90a3
fix(ds): Allow to write batches to older generations 2024-05-22 20:28:16 +02:00
Thales Macedo Garitezi 5cad4497de fix(monitor api): add ds connections and subscriptions to old counters
Fixes https://emqx.atlassian.net/browse/EMQX-12423
Fixes https://emqx.atlassian.net/browse/EMQX-12267
2024-05-22 15:19:46 -03:00
Thales Macedo Garitezi 3f23548cc5
Merge pull request #13090 from thalesmg/fix-reconnect-action-disabled-connector-r57-20240522
fix(bridge v2 api): don't attempt to start disabled connector when starting action/source
2024-05-22 14:31:40 -03:00
zmstone 927b1337fa chore: update dashboard version 2024-05-22 19:06:54 +02:00
Thales Macedo Garitezi 4094032649 fix(bridge v2 api): don't attempt to start disabled connector when starting action/source
Fixes https://emqx.atlassian.net/browse/EMQX-12435
2024-05-22 13:33:55 -03:00
zmstone 1bc9600c58 Merge remote-tracking branch 'origin/release-57' 2024-05-22 18:28:23 +02:00
Kjell Winblad 88c96e26de refactor: simplify the code with maps:map/2
Thanks @thalesmg for the suggestion
2024-05-22 18:03:43 +02:00
ieQu1 59a09fb86f
fix(ds): Apply review remarks 2024-05-22 18:01:33 +02:00
ieQu1 5c78ecba40
docs(ds): Update documentation for the storage layouts 2024-05-22 18:01:33 +02:00
ieQu1 29345aaa30
fix(ds): Fix idle event generation in bitfield_lts layout 2024-05-22 18:01:33 +02:00
ieQu1 b3ded7edce
fix(ds): Fix code review remark 2024-05-22 18:01:33 +02:00
ieQu1 60edf5e9b8
fix(ds): Move responsibility of returning end_of_stream to the CBM 2024-05-22 18:01:33 +02:00
ieQu1 0ff307e789
fix(ds): Include generation ID in the storage events
Make sure storage events originating from generation X are handled in
the context of the same generation.
2024-05-22 18:01:33 +02:00
ieQu1 acdae4fba3
fix(ds): Workaround for the idempotency error when dropping gens 2024-05-22 18:01:33 +02:00
ieQu1 eb7c43ee9d
fix(ds): Always store messages in the current generation 2024-05-22 18:01:33 +02:00
ieQu1 074d98a14a
test(ds): Refactor ds_SUITE 2024-05-22 18:01:33 +02:00
ieQu1 e4a73f003a
feat(ds): Implement format_status callback
Reduce volume of logs and crash reports from DS
2024-05-22 18:01:32 +02:00
ieQu1 1526c527d0
fix(ds): Log generation operations 2024-05-22 18:01:32 +02:00
ieQu1 aca2d9586c
fix(ds): Fix return type of drop_generation 2024-05-22 18:01:32 +02:00
ieQu1 c6fc76e335
fix(ds): Perform read operations on the leader. 2024-05-22 18:01:32 +02:00
ieQu1 4580906405
fix(ds): Use erpc instead of gen_rpc for `delete_next' 2024-05-22 18:01:32 +02:00
Andrew Mayorov 8016e9adf4
fix(s3-bridge): restore backward config compatibility 2024-05-22 17:59:52 +02:00
Zaiming (Stone) Shi d4acceb858
Merge pull request #13091 from thalesmg/ci-fix-ce-elixir-build-r57-20240522
ci: fix emqx ce elixir build
2024-05-22 17:50:17 +02:00
Kjell Winblad 4b540e3bd0 fix: do not leak action configurations in alarm messages 2024-05-22 17:43:07 +02:00
Andrew Mayorov e6c5c1b598
chore(dsrepl): provide more information in rebalancing log messages 2024-05-22 17:24:08 +02:00
Andrew Mayorov c355c9ad50
fix(dsrepl): properly handle transaction abort during forget site 2024-05-22 17:22:55 +02:00
Thales Macedo Garitezi 5c9f1d9401 ci: fix emqx ce elixir build 2024-05-22 11:49:10 -03:00
Kjell Winblad cff8b97e8a fix: handle channel updated during health check
This commit fixes an issue found by CI test case
emqx_bridge_influxdb_SUITE:t_start_stop and others. While the channel
health check process is running, the channel could be removed or updated
which could cause a crash in the resource manager or non up-to-date
alarms being triggered.
2024-05-22 12:15:04 +02:00
Kjell Winblad 39d758c4d6 fix: do not return configs for channels from emqx_resource_manager 2024-05-22 12:15:04 +02:00
Kjell Winblad 331f9a1b96 docs: add change log entry 2024-05-22 12:15:04 +02:00
Kjell Winblad 917474f694 fix: action config update would sometimes not be reflected in connector
Before this commit the following happened sometimes:

1. action status is connected
2. action config is updated to something that should change the status to
   disconnected
3. action status is still connected and the old config is being used by
   the connector even though the config has been correctly updated.

The reason for this bug is that the post_config_hook runs before the
global EMQX config is updated. The post config hook is adding the new
config to the connector. Since the new config causes the action to get
status disconnected, the adding of the action to the connector is
retried when the health check runs but this time the config will be
loaded from the global config which could cause the old config to be
loaded (this happens when the global config has not had time to get
updated).

The above problem has been fixed in this commit by only reading action
configs from the global config when the connector starts/restarts and
instead store the latest configs for the actions in the connector.

Fixes:
https://emqx.atlassian.net/browse/EMQX-12376
2024-05-22 12:15:04 +02:00
firest f3e8037e0f fix(rocketmq): fix namespace error for RocketMQ 2024-05-22 16:29:38 +08:00
Andrew Mayorov a3cd3e31b1
Merge pull request #13084 from keynslug/fix/EMQX-12422/part-size
fix(s3-bridge): report inconsistent `min/max_part_size` option
2024-05-22 09:48:09 +02:00
JimMoen e5f7aa9817
refactor: plguin functions and types rename 2024-05-22 11:51:54 +08:00
JimMoen 33aa61daea
fix: use hocon format as plugin config 2024-05-22 06:37:58 +08:00
JimMoen 14f2a68799
fix: bpapi spec type 2024-05-22 06:01:57 +08:00
Thales Macedo Garitezi 31a35f2a15
Merge pull request #13076 from thalesmg/fix-ds-session-count-client-api-r57-20240520
fix(client mgmt api): cache disconnected durable session count for `/clients` api
2024-05-21 15:34:21 -03:00
JimMoen 5abd23af5a
test: plugin refactor 2024-05-22 02:09:37 +08:00
JimMoen 87b3b214b9
fix: make static_check happy 2024-05-22 02:09:36 +08:00
JimMoen 3ce091e9d7
fix: ensure plugin tarball and extracted 2024-05-22 02:09:35 +08:00
JimMoen 1abc8cf502
fix: ensure plugin's config on boot and join cluster 2024-05-22 02:09:34 +08:00
JimMoen 677352e498
fix: ensure installed and plugin state on boot 2024-05-22 02:09:33 +08:00
JimMoen 2076681e76
fix: put plugin config with binary namevsn key 2024-05-22 02:09:32 +08:00
JimMoen 140b7ce51e
fix(plugin): schema content only provided in enterprise edition 2024-05-22 02:09:31 +08:00
JimMoen a7f2f95318
fix: ensure avro file 2024-05-22 02:09:30 +08:00
JimMoen df7dcb2764
fix: do not let plugin start failed lead emqx start failed 2024-05-22 02:09:29 +08:00
JimMoen e0e4517d9e
fix: ensure plugin config on boot 2024-05-22 02:09:28 +08:00
JimMoen e8d4e88118
fix(plugin): serde not found on new-joined nodes 2024-05-22 02:09:26 +08:00
JimMoen 4bc80ee483
build: unsupported otp23 and otp24 casued `maybe_expr` introduced 2024-05-22 02:09:25 +08:00
JimMoen 4ad0743f61
Merge pull request #13081 from JimMoen/fix-typo
chore: fix typos
2024-05-22 02:05:20 +08:00
Andrew Mayorov 28f6eb0200
fix(s3-bridge): report inconsistent `min/max_part_size` option 2024-05-21 18:49:01 +02:00
SergeTupchiy 528d6b7ef1
Merge pull request #13082 from SergeTupchiy/routes-fixes
Minor routes fixes
2024-05-21 19:11:47 +03:00
ieQu1 72c0ada578
Merge pull request #13061 from ieQu1/dev/merge-release57-240516
Sync release-57 to master
2024-05-21 17:47:26 +02:00
Serge Tupchii 38e57e321f fix(ds_router): return correct type from lookup_routes/1, fix fun specs 2024-05-21 16:31:31 +03:00
Serge Tupchii 0db6b8dc54 fix(emqx_router): return correct type from lookup_routes/1 (v2 schema) 2024-05-21 16:28:59 +03:00
ieQu1 acb19a06cf Merge remote-tracking branch 'origin/release-57' 2024-05-21 15:04:46 +02:00
Thales Macedo Garitezi 7c5cb1acc5 fix(monitor current api): expose `disconnected_durable_sessions` count
Fixes https://emqx.atlassian.net/browse/EMQX-12423
2024-05-21 10:03:09 -03:00
JimMoen bb3c66638c
chore: fix typos 2024-05-21 17:45:20 +08:00
JianBo He 4f341bef8b
Merge pull request #12920 from cisiqo/patch-6
fix: STOMP heartbeat
2024-05-21 16:57:58 +08:00
zmstone 7696f78d07 docs: add changelog for pr 13070 2024-05-21 09:30:06 +02:00
Thales Macedo Garitezi 8b4a1c3d75 fix(client mgmt api): cache disconnected durable session count for `/clients` api
Fixes https://emqx.atlassian.net/browse/EMQX-12396
2024-05-20 11:48:08 -03:00
Kjell Winblad 8279d8c787
Merge pull request #13053 from kjellwinblad/kjell/fix_rule_trace_issues/EMQX-12327/EMQX-12335/EMQX-12336
Fix small action trace issues
2024-05-20 16:25:38 +02:00
Thales Macedo Garitezi 8f9942149a
Merge pull request #13075 from thalesmg/hide-clientsv2-api-r57-20240520
docs: hide `/clients_v2` from swagger api docs
2024-05-20 10:53:03 -03:00
Thales Macedo Garitezi a5d973b681 docs: hide `/clients_v2` from swagger api docs
Since it's not yet ready for production, we'll hide it from the API docs.
2024-05-20 10:00:43 -03:00
Kjell Winblad 3c87bcde46 fix(rule trace): restore logger metadata to its previous value 2024-05-20 10:57:15 +02:00
Zaiming (Stone) Shi 7880353224
Merge pull request #13071 from emqx/0518-bump-app-vsn
chore: bump emqx_auth_http app vsn
2024-05-19 21:42:32 +02:00
zhongwencool 02097b577c
Merge pull request #13064 from zhongwencool/influxdb-client-failed-msg
chore: improved InfluxDB connection error messaging
2024-05-19 16:20:13 +08:00
zmstone 905e116b6b chore: allow non-strict semver bump for listed app-version 2024-05-19 09:53:34 +02:00
zmstone 6940930c3e chore: bump emqx_auth_http app vsn 2024-05-19 09:30:39 +02:00
zmstone 331d44a78a chore: improve Kafka producer health-check error logs
The Kafka producer lib wolff returns detailed error logs
about which host:port had issue, EMQX should log them to help
troubleshooting
2024-05-18 19:12:51 +02:00
zmstone c3bc3cc514 chore: ctl command run may return 'true' 2024-05-18 18:48:30 +02:00
Zaiming (Stone) Shi c6ee37bacd
Merge pull request #13068 from zmstone/0517-fix-dynamic-license-usage-for-dashboard
fix(license): show dynamic max_connections for bc
2024-05-18 09:49:18 +02:00
Andrew Mayorov fc3f525a67
Merge pull request #13066 from keynslug/fix/s3-bridge/desc-html
chore(s3-bridge): decrease default aggregation settings
2024-05-17 19:43:19 +02:00
Thales Macedo Garitezi d37edd69ae
Merge pull request #13067 from thalesmg/fix-ds-monitor-subs-r57-20240517
fix(dssubs): introduce separate gauge for subscriptions from durable sessions
2024-05-17 13:49:09 -03:00
zmstone b3afff9638 fix(license): show dynamic max_connections for bc 2024-05-17 17:44:21 +02:00
Thales Macedo Garitezi 388e6c8262 fix(dssubs): introduce separate gauge for subscriptions from durable sessions
Fixes https://emqx.atlassian.net/browse/EMQX-12267
2024-05-17 10:17:16 -03:00
Kjell Winblad 5ce095f30e fix(rule trace): only include stop_after_rendering when value is true 2024-05-17 14:53:14 +02:00
Andrew Mayorov 385ac268d7
chore(s3-bridge): decrease default aggreg interval to 30 minutes 2024-05-17 14:49:18 +02:00
Andrew Mayorov c348f759af
chore(s3-bridge): decrease default aggreg limit to 100K records 2024-05-17 14:19:59 +02:00
Andrew Mayorov 7e6f61f818
fix(s3-bridge): properly format bulleted list in field description 2024-05-17 14:13:49 +02:00
Kjell Winblad 2e6db85578 fix(rule trace): rename rule_trigger_time(s) and cleaups
This commit renames trace fields rule_trigger_time and
rule_trigger_times to rule_trigger_ts and makes sure that the value for
rule_trigger_ts will always be a list of timestamps.
2024-05-17 14:13:36 +02:00
Andrew Mayorov 4d1db9f847
Merge pull request #13059 from keynslug/feat/EMQX-12204/single-action-schema
feat(s3-bridge): meld 2 separate actions into a single one
2024-05-17 13:27:40 +02:00
Kjell Winblad 2209b26fa5 fix(rule trace): do not leak trace meta data when tracing action result
Fixes:
https://emqx.atlassian.net/browse/EMQX-12391
2024-05-17 10:05:33 +02:00
ieQu1 5ba71ae6f7
Merge pull request #13062 from ieQu1/dev/ds-better-naming
fix(sessds): Rename last_alive_update_interval -> heartbeat_interval
2024-05-17 09:55:40 +02:00
Andrew Mayorov 39c2433afb
fix(s3-bridge): update config typespecs 2024-05-17 09:47:16 +02:00
Andrew Mayorov 86f99959b0
Merge pull request #13054 from keynslug/fix/EMQX-12365/node-leave
fix(dsrepl): anticipate and handle nodes leaving the cluster
2024-05-17 09:43:15 +02:00
Andrew Mayorov 5b2c2b336c
feat(s3-bridge): meld 2 separate actions into a single one
Discriminated through `mode` parameter. Also rename "simple" action to
a "direct" upload mode.
2024-05-17 09:34:21 +02:00
zhongwencool b4eb910cb1 chore: improved InfluxDB connection error messaging 2024-05-17 10:38:11 +08:00
zhongwencool 1ac7aa151e
Merge pull request #13048 from thalesmg/sv-backup-r57-20240514
feat(schema validation): implement backup restore
2024-05-17 09:47:04 +08:00
ieQu1 6f30c1c541
fix(sessds): Rename last_alive_update_interval -> heartbeat_interval 2024-05-17 01:20:10 +02:00
ieQu1 93f1a158f7
Merge pull request #13060 from ieQu1/dev/ds-better-naming
Better naming of DS database and configuration
2024-05-16 22:03:23 +02:00
ieQu1 73f17249e9
fix(sessds): Rename session_persistence to durable_sessions 2024-05-16 21:31:32 +02:00
ieQu1 ee6e7174cf
fix(sessds): Rename the durable messages DB to `messages` 2024-05-16 21:31:32 +02:00
Andrew Mayorov 5157e61418
fix(dsrepl): verify if shards already allocated first 2024-05-16 18:56:54 +02:00
Andrew Mayorov 0119728d45
feat(dsrepl): also reflect pending transitions in ds status 2024-05-16 18:56:21 +02:00
Andrew Mayorov 26c4a4f597
feat(dsrepl): reflect conflicts and inconsistencies in ds status 2024-05-16 18:32:08 +02:00
Andrew Mayorov 7e86e3e61c
fix(dsrepl): anticipate and handle nodes leaving the cluster
Also make `claim_site/2` safer by refusing to claim a site for a node
that is already there.
2024-05-16 18:32:07 +02:00
Kjell Winblad ed16e678be fix(rule apply test): add default values to context
Fixes:
https://emqx.atlassian.net/browse/EMQX-12378
2024-05-16 17:31:44 +02:00
Kjell Winblad 520e91c8fd fix(greptime trace): remove async info as it is confusing
Fixes:
https://emqx.atlassian.net/browse/EMQX-12385
2024-05-16 16:50:09 +02:00
Ilia Averianov 22d5f17de8
Merge pull request #13025 from savonarola/0513-fix-cursor-usage
Get rid of qlc in retainer
2024-05-16 17:06:53 +03:00
Kjell Winblad b7c2f4a6d7 fix(best_effor_json): make tuple list check more efficient 2024-05-16 15:40:38 +02:00
Ilya Averyanov 1a664c941b chore(retainer): scan table in batches, improve stream usage
Co-authored-by: Thales Macedo Garitezi <thalesmg@gmail.com>
Co-authored-by: Zaiming (Stone) Shi <zmstone@gmail.com>
2024-05-16 16:06:11 +03:00
Kjell Winblad ba74135079
Merge pull request #13052 from kjellwinblad/kjell/evaluate_lazy_trace_values_in_normal_log_formatters/EMQX-12380
fix: evaluate lazy values in normal log formatters when level is debug
2024-05-16 15:02:53 +02:00
Thales Macedo Garitezi 34a29e6363 feat(schema validation): implement support for `ctl conf load` 2024-05-16 09:55:42 -03:00
Ilia Averianov 322989c83f
Merge pull request #13040 from savonarola/0513-fix-http-authn-error-handling
fix(auth_http): fix query encoding
2024-05-16 15:12:57 +03:00
Zaiming (Stone) Shi 0be1249bbe
Merge pull request #13041 from zmstone/0513-http-authn-header-missing-should-result-in-meaningful-error-message
0513 http authn header missing should result in meaningful error message
2024-05-16 13:17:20 +02:00
ieQu1 71b393be89
Merge pull request #13057 from ieQu1/dev/default-n-shards
fix(ds): Change the default number of shards to 12
2024-05-16 13:05:34 +02:00
Kjell Winblad 413ad60bdb fix(cassandra): format rendered trace in a better way
Fixes:
https://emqx.atlassian.net/browse/EMQX-12393
2024-05-16 11:35:12 +02:00
Kjell Winblad 9fd8e930be fix(best_effort_json): only do tuple list to map without losing pairs 2024-05-16 11:19:48 +02:00
Ilya Averyanov e1ce6377f3 chore(streams): add stream methods, optimize streams 2024-05-16 12:04:08 +03:00
Ilia Averianov 1f7e358e1e
Merge pull request #13006 from savonarola/0509-fix-retainer-banned
fix(banned): verify delayed/taken over/retained messages against clientid_re ban rules
2024-05-16 11:37:15 +03:00
Ilya Averyanov f2d26b9972 chore(auth_http): add changelog
Co-authored-by: Thales Macedo Garitezi <thalesmg@gmail.com>
2024-05-16 11:36:52 +03:00
zmstone 2acde5a4e4 fix(authn/http): log meaningful error message if http header is missing 2024-05-16 11:36:52 +03:00
zmstone 4fb484d4cf chore(emqx_schema): change atom array to enum array for alarm.actions 2024-05-16 11:36:52 +03:00
Ilya Averyanov daf2e5a444 chore(auth_http): unify http request generation
Co-authored-by: Thales Macedo Garitezi <thalesmg@gmail.com>
2024-05-16 11:36:52 +03:00
Kjell Winblad cf5b464777
Merge pull request #12937 from kjellwinblad/kjell/add_use_legacy_protocol_option_to_mongodb_auth/EMQX-12245
test(mongodb authn, authz): add test cases for use_legacy_protocol
2024-05-16 10:10:17 +02:00
Kjell Winblad 72b0c63ed2
Merge pull request #13043 from kjellwinblad/kjell/kafka_incorrect_query_type/EMQX-12363
fix(kafka trace): do not include query type in trace entry
2024-05-16 10:08:16 +02:00
ieQu1 deffb01544
fix(ds): Change the default number of shards to 12 2024-05-16 08:06:07 +02:00
Ilya Averyanov 552b62236c chore(retainer): move filter/foreach to emqx_utils_stream 2024-05-15 19:09:06 +03:00
Ilya Averyanov 0b39aaadbd chore(retainer): get rid of qlc usage 2024-05-15 19:09:06 +03:00
Thales Macedo Garitezi 2eb1bb2b13
Merge pull request #13032 from kjellwinblad/kjell/no_ctx_message_validation_failed/EMQX-12354
fix: add handling of message_validation_failed ctx for rule testing
2024-05-15 11:20:18 -03:00
Thales Macedo Garitezi bde17158e9
Merge pull request #13051 from thalesmg/test-add-more-context-debug-m-20240514
test: attempt to stabilize a couple flaky tests
2024-05-15 10:29:27 -03:00
Kjell Winblad 246bce85ec fix: make mysql action rendered trace include parameters
When doing non-batch inserts with the MySQL action, prepared statements
are used. We therefore need to include the parameters to the prepared
statement when tracing the rendered templates.

Fixes:
https://emqx.atlassian.net/browse/EMQX-12335
2024-05-15 14:49:33 +02:00
Kjell Winblad c72682d81b fix: remove query mode from redis action trace as it only supports sync
Fixes:
https://emqx.atlassian.net/browse/EMQX-12336
2024-05-15 14:32:15 +02:00
Ilya Averyanov 78a87ab5a6 fix(banned): verify delayed/taken over/retained messages against clientid_re rules 2024-05-15 14:05:38 +03:00
Kjell Winblad 8cbfc4c0cd fix: evaluate lazy values in normal log formatters when level is debug
Fixes:
https://emqx.atlassian.net/browse/EMQX-12380
2024-05-15 11:47:21 +02:00
lafirest faf3492e58
Merge pull request #13039 from lafirest/fix/rocket_key
fix(rocketmq): fix a typo and a RocketMQ encoding error
2024-05-15 15:28:35 +08:00
Andrew Mayorov 3e1e4bab17
Merge pull request #13047 from keynslug/fix/EMQX-12366/api-ds-leave
feat(api-ds): provide more information on nonexistent site leave
2024-05-14 23:21:07 +02:00
Thales Macedo Garitezi bcbeadd4af test: stabilize flaky test 2024-05-14 17:53:29 -03:00
Thales Macedo Garitezi f062517ccb test: stabilize flaky test 2024-05-14 17:53:29 -03:00
Thales Macedo Garitezi b0aa7f25aa test: add more context to help debug flaky test
Ex: https://github.com/emqx/emqx/actions/runs/9084293110/job/24967912514?pr=13050#step:6:18330
2024-05-14 17:53:29 -03:00
Thales Macedo Garitezi e67b078775
Merge pull request #13050 from thalesmg/ci-spellcheck-opts-m-20240514
ci: allow customizing number of jobs when running locally
2024-05-14 17:25:54 -03:00
Thales Macedo Garitezi 202e145db7
Merge pull request #13049 from thalesmg/sync-r57-m-20240514
sync `release-57` to `master`
2024-05-14 16:01:57 -03:00
Thales Macedo Garitezi fd949240c0 feat(schema validation): implement backup restore
Fixes https://emqx.atlassian.net/browse/EMQX-12346
2024-05-14 15:58:19 -03:00
Thales Macedo Garitezi bc5071590b
Merge pull request #13033 from thalesmg/fix-ds-more-client-api-fields-r57-20240513
fix(ds clients mgmt api): add more fields to disconnected durable sessions
2024-05-14 15:29:40 -03:00
Thales Macedo Garitezi 7023e6ad96
Merge pull request #13017 from thalesmg/fix-ds-subs-pages-r57-20240510
fix(subs mgmt api): attempt to return mixed clients ds/non-ds in the same page
2024-05-14 15:29:29 -03:00
Thales Macedo Garitezi db125d54dd ci: allow customizing number of jobs when running locally
Example:

```sh
ͳ scripts/spellcheck/spellcheck.sh -j 20 _build/docgen/emqx-enterprise/schema-en.json
Adding /dicts/emqx.txt
Starting LanguageTool server...
+ java -Xms256m -Xmx512m -cp languagetool-server.jar org.languagetool.server.HTTPServer --port 8010 --public --allow-origin '*' --config config.properties
Checking /schema.json with 20 processes...
Spellcheck OK
```
2024-05-14 15:20:16 -03:00
Thales Macedo Garitezi 2a0ac34656 Merge branch 'release-57' into sync-r57-m-20240514 2024-05-14 15:03:04 -03:00
Kjell Winblad e811f4a392 fix: add handling of message_validation_failed ctx for rule testing
Before this commit, the backend could not handle the test context for
message_validation_failed events that could be sent from the dashboard
since no handling code for this contexts existed in the backend. This
has now been fixed by adding such handling code.

Fixes:
https://emqx.atlassian.net/browse/EMQX-12354
2024-05-14 13:07:32 -03:00
Thales Macedo Garitezi 1730a41337
Merge pull request #13046 from thalesmg/refactor-mv-rename-sv-r57-20240514
refactor: rename `message_validation` to `schema_validation`
2024-05-14 13:03:12 -03:00
Kjell Winblad adbc392265
Merge pull request #13027 from kjellwinblad/kjell/fix_trace_json_report_formatting/EMQX-12344
fix: JSON trace formatter should handle report style log entries
2024-05-14 18:02:59 +02:00
firest 437a0c0d55 fix(rocketmq): fix a typo and a RocketMQ encoding error 2024-05-14 23:01:31 +08:00
Andrew Mayorov 2f90d15ce6
fix(ds-api): adapt CLI to API changes 2024-05-14 16:55:17 +02:00
Andrew Mayorov 35e360fcbe
feat(api-ds): provide more information on nonexistent site leave 2024-05-14 15:57:41 +02:00
Thales Macedo Garitezi 257dae5211 refactor: rename `message_validation` to `schema_validation`
Request from Product team.

Fixes https://emqx.atlassian.net/browse/EMQX-12383
2024-05-14 10:32:27 -03:00
lafirest dc391d2403
Merge pull request #13009 from lafirest/fix/rate_log
feat(limiter): lift the log level of rate limiter to `warning`
2024-05-14 21:11:26 +08:00
Thales Macedo Garitezi 15acd86b31
Merge pull request #13034 from thalesmg/test-flaky-mq-r57-20240513
test(client mgmt api): attempt to fix flaky test
2024-05-14 09:01:29 -03:00
Thales Macedo Garitezi e8d2c48d3c
Merge pull request #13018 from thalesmg/fix-postgres-log-spam-r57-20240510
fix(postgres): reduce log spamming when connection goes down
2024-05-14 09:00:36 -03:00
Kjell Winblad f75c7a5cea fix(trace log entry error): better structure and naming 2024-05-14 13:38:41 +02:00
Andrew Mayorov 74ed0f578a
Merge pull request #13042 from keynslug/fix/EMQX-12204/api-ns
fix(s3-aggreg): disambiguate action schema namespace
2024-05-14 13:12:34 +02:00
Kjell Winblad 121084b2ff fix(kafka trace): do not include query type in trace entry
For Kafka that has its internal buffering the on_query_async callback is
used both for sync and async queries (for sync queries the caller waits
for a response directly after calling on_query_async). Therefore, before
this commit, the trace included incorrect query type information. This
has been fixed by removing the query type information from the trace.
This should be okay since the query type is not essential information
and can be derived from the configuration.

Fixes:
https://emqx.atlassian.net/browse/EMQX-12363
2024-05-14 12:24:30 +02:00
ieQu1 525e4dac95
Merge pull request #13036 from ieQu1/dev/reduce-log-spam
tests: Reduce log spam in the failed test suites
2024-05-14 10:53:30 +02:00
ieQu1 f663373c57
Merge pull request #13037 from ieQu1/dev/merge-release57-240513
Sync release-57 to the master
2024-05-14 10:50:30 +02:00
Andrew Mayorov c10a48f4be
fix(s3-aggreg): disambiguate action schema namespace
Otherwise schemas for `s3` and `s3_aggregated_upload` collide when
projected into OpenAPI schema.
2024-05-14 10:49:21 +02:00
zmstone 5983b7c6f2 docs: add changelog for PR 13041 2024-05-14 10:26:35 +02:00
zmstone 93232d4253 fix(authn/http): log meaningful error message if http header is missing 2024-05-14 10:22:07 +02:00
Andrew Mayorov 98a93662c1
Merge pull request #13035 from keynslug/fix/EMQX-12291/pers-sys-msg
fix(sessds): persist $SYS messages as well
2024-05-14 10:05:49 +02:00
Zaiming (Stone) Shi 34bf291539
Merge pull request #13024 from zmstone/0513-deny-plush-hash-by-default-ACL
fix: deny subscribing to +/# by default ACL
2024-05-14 09:43:42 +02:00
firest 7a7bd84cba fix(limiter): improved log content 2024-05-14 15:34:13 +08:00
Ilya Averyanov bca3782d73 fix(auth_http): fix query encoding
* ignore authenticator if JSON format is set up for requests, but non-utf8 data is going to be sent
* use application/json format by default
* fix encoding of query part of the requests
2024-05-14 10:32:53 +03:00
ieQu1 25c6ac3d16
Merge remote-tracking branch 'origin/release-57' 2024-05-13 22:05:29 +02:00
ieQu1 ac3f5a083d
test: Reduce log spam in the failed test suites 2024-05-13 22:00:33 +02:00
ieQu1 8506ca7919
Merge pull request #12998 from ieQu1/dev/improve-latency
Use leader's clock when calculating LTS cutoff timestamp
2024-05-13 21:54:06 +02:00
Andrew Mayorov 66b7ac4c45
fix(sessds): persist $SYS messages as well
Otherwise, persistent sessions will not be able to receive $SYS messages
whatsoever.
2024-05-13 21:27:55 +02:00
Thales Macedo Garitezi a2a5fd1f8e test(client mgmt api): attempt to fix flaky test
```
%%% emqx_mgmt_api_clients_SUITE ==> msgs_plain_encoding.t_mqueue_messages: FAILED
%%% emqx_mgmt_api_clients_SUITE ==>
Failure/Error: ?assertEqual(79, Count)
  expected: 79
       got: 100
      line: 1303
```
2024-05-13 15:53:21 -03:00
ieQu1 3da3a36863
test(ds): Add generation in the replication suite 2024-05-13 19:51:04 +02:00
ieQu1 9f7ef9f34f
fix(ds): Apply review remarks 2024-05-13 19:35:24 +02:00
Thales Macedo Garitezi e7c47f4ec0 fix(ds clients mgmt api): add more fields to disconnected durable sessions
Fixes https://emqx.atlassian.net/browse/EMQX-12369
2024-05-13 14:25:02 -03:00
Kjell Winblad 1c34a84dd2
Merge pull request #13028 from kjellwinblad/kjell/swagger_example_missing_ruleid_paramter/EMQX-12325
fix: include ruleid parameter in swagger example for apply rule endpoint
2024-05-13 17:35:31 +02:00
Thales Macedo Garitezi 81473519bd
Merge pull request #13031 from thalesmg/fix-clientsv2-sec-r57-20240513
fix(client mgmt api): require authn for endpoint
2024-05-13 12:17:31 -03:00
Thales Macedo Garitezi a31d05d1ce
Merge pull request #13030 from thalesmg/fix-ds-return-expired-sessions-api-r57-20240513
fix(client mgmt api): return expired durable sessions with `is_expired: true`
2024-05-13 12:11:58 -03:00
Thales Macedo Garitezi 39899b917d fix(client mgmt api): require authn for endpoint
Fixes https://emqx.atlassian.net/browse/EMQX-12361
2024-05-13 10:54:21 -03:00
Thales Macedo Garitezi 6b032faebc fix(client mgmt api): return expired durable sessions with `is_expired: true`
Fixes https://emqx.atlassian.net/browse/EMQX-12274
2024-05-13 10:51:24 -03:00
Thales Macedo Garitezi 6e03479fd7
Merge pull request #13019 from thalesmg/fix-rocketmq-label-r57-20240510
docs(rocketmq): add missing label
2024-05-13 10:25:50 -03:00
Thales Macedo Garitezi 0dee2d67b1 fix: always check if first query has more rows 2024-05-13 09:10:18 -03:00
Kjell Winblad c8690a8273 fix: include ruleid parameter in swagger example for apply rule endpoint
Fixes:
https://emqx.atlassian.net/browse/EMQX-12325
2024-05-13 12:28:17 +02:00
Kjell Winblad 921d82f083 fix: JSON trace formatter should handle report style log entries
Fixes:
https://emqx.atlassian.net/browse/EMQX-12344
2024-05-13 12:11:11 +02:00
zmstone 7faf73e0f4 chore(emqx_schema): change atom array to enum array for alarm.actions 2024-05-13 10:54:33 +02:00
zmstone 290ebe2fc5 fix: deny subscribing to +/# by default ACL
Prior to this change, EMQX default ACL has a deny rule to reject
subscribing to `#`.
For completeness, the default ACL should also deny `+/#` because
they are essentially equivalent.
2024-05-13 09:26:42 +02:00
JianBo He 54f6bd181b
Merge pull request #13010 from JimMoen/fix-jt808-reg-failed
fix(gw): jt808 REG_ACK failed due to faulty clientinfo
2024-05-13 14:19:18 +08:00
Ivan Dyachkov ac9da9d8a2
Merge pull request #13016 from id/0510-update-ce-only-workflows
ci: some scheduled workflows should only run on emqx/emqx
2024-05-11 14:26:01 +02:00
Ivan Dyachkov e92d1f4468 build(pkg): fix pkg-tests.sh for ubuntu 24.04 2024-05-11 10:50:40 +02:00
JimMoen 2f212f34a3
Merge pull request #12989 from JimMoen/fix-plugin-config-file-backup
fix(plugin): add a backup for the plugin config file
2024-05-11 16:38:36 +08:00
Ivan Dyachkov c08c8cef22 ci(docker): login to specific docker registry only when necessary 2024-05-11 10:18:46 +02:00
JimMoen a5ecceb755
chore: apply suggestions from code review, thanks @thalesmg 2024-05-11 11:36:40 +08:00
Thales Macedo Garitezi e25fe62cbc fix(subs mgmt api): attempt to return mixed clients ds/non-ds in the same page
Fixes https://emqx.atlassian.net/browse/EMQX-12294
2024-05-10 14:48:46 -03:00
Thales Macedo Garitezi c7c04bbdeb docs(rocketmq): add missing label
Fixes https://emqx.atlassian.net/browse/EMQX-12339
2024-05-10 13:45:25 -03:00
Kjell Winblad c6df069c5a
Merge pull request #13012 from kjellwinblad/kjell/fix_incorrect_config_crash/EMQX-12315
fix: listener crash if access_rules config option is incorrect
2024-05-10 17:46:40 +02:00
Thales Macedo Garitezi c02701dfa1
Merge pull request #13015 from thalesmg/sync-r57-m-20240510
sync `release-57` to `master`
2024-05-10 12:18:02 -03:00
Thales Macedo Garitezi f690db9849 fix(postgres): reduce log spamming when connection goes down
Fixes https://emqx.atlassian.net/browse/EMQX-12334

See also: https://github.com/emqx/epgsql/pull/10
2024-05-10 12:15:01 -03:00
JimMoen 91a5644b0e
docs: add changelog for PR #13010 2024-05-10 23:09:23 +08:00
JimMoen 3c7e8a3bd5
test(gw): jt808 register failed 2024-05-10 23:09:22 +08:00
JimMoen f8fd4d15be
fix(gw): process jt808 client deregister packet 2024-05-10 23:00:59 +08:00
Ivan Dyachkov d4450d543b ci: ensure unique name for artifacts in scheduled packages workflow 2024-05-10 17:00:41 +02:00
Ivan Dyachkov 7ab06bcdc9 ci: some scheduled workflows should only run on emqx/emqx 2024-05-10 16:24:21 +02:00
Zaiming (Stone) Shi c491b83857
Merge pull request #13014 from zmstone/0510-add-is_template-for-kinesis-partition-key
fix(kinesis): partition_key should be of 'template' type
2024-05-10 16:11:35 +02:00
Kjell Winblad b13fa37771 fix: dialyzer warning 2024-05-10 15:51:28 +02:00
Ivan Dyachkov 5094ce4ef6
Merge pull request #13013 from id/0510-update-coveralls-integration
ci: send data to coveralls from emqx/emqx only
2024-05-10 15:45:38 +02:00
Thales Macedo Garitezi 6be4e6f631 Merge branch 'release-57' into sync-r57-m-20240510 2024-05-10 10:23:28 -03:00
Thales Macedo Garitezi 0eaef18391
Merge pull request #13005 from thalesmg/fix-aggreg-sup-tree-r57-20240509
fix(aggregator): refactor supervision tree
2024-05-10 10:22:33 -03:00
Kjell Winblad 0d053a6897 docs: add change log entry 2024-05-10 14:29:35 +02:00
Kjell Winblad 2bed5894e3 test: add test cases for listeners access_rules validation and split 2024-05-10 14:21:43 +02:00
Thales Macedo Garitezi 3a29696a48 fix(aggregator): refactor supervision tree
Instead of using a aggregator supervisor with a fixed local name, we should allow
specifying different names so each action app will spawn its own aggregator supervisor.
2024-05-10 09:06:12 -03:00
zmstone 47df968d4a fix(kinesis): partition_key should be of 'template' type 2024-05-10 13:57:38 +02:00
Ivan Dyachkov 37b959a3e9 ci: send data to coveralls from emqx/emqx only
also optimize cover reports - submit in parallel
2024-05-10 13:37:32 +02:00
firest bd7ccc3546 chore: update change 2024-05-10 18:48:51 +08:00
firest 1fefb421bc feat(limiter): lift the log level of rate limiter to `warning` 2024-05-10 18:47:55 +08:00
Kjell Winblad 0aeb2cd77f fix: listener crash if access_rules config option is incorrect
Previously when changing the access_rules configuration option of a
listener to something that was not a valid rule, the listener would
crash. This has now been fixed by the addition of a configuration
validator that checks the access_rules field.

Additionally, a configuration option converter has been added to the
access_rules field so that one can specify several rules in a single
string by using "," (comma) as separator.

Fixes:
https://emqx.atlassian.net/browse/EMQX-12315
2024-05-10 12:27:04 +02:00
JimMoen 1a6f0c9234
chore: bump gw_jt808 app vsn 2024-05-10 17:13:23 +08:00
JimMoen b07242515f
fix(gw): jt808 REG_ACK failed due to faulty clientinfo 2024-05-10 17:12:28 +08:00
Ivan Dyachkov 900536712d
Merge pull request #12997 from thalesmg/sync-r57-m-20240508
sync `release-57` to `master`
2024-05-10 10:41:30 +02:00
Kjell Winblad 8c0b55a89e
Merge pull request #12992 from kjellwinblad/kjell/fix_rule_unescape_function/EMQX-12313
fix: make rule engine unescape convert \a to the terminal alarm char
2024-05-10 09:48:33 +02:00
lafirest da7b11020a
Merge pull request #13001 from lafirest/fix/sysk_reconn
fix(sysk): fix that the syskeeper forwarding never reconnecting
2024-05-10 11:24:28 +08:00
firest 1f3b640a3d chore: update change 2024-05-10 07:29:14 +08:00
Thales Macedo Garitezi e9af99c625
Merge pull request #13003 from thalesmg/fix-aggreg-name-r57-20240509
fix(aggregator): namespace aggregator ids with action type
2024-05-09 17:25:06 -03:00
Thales Macedo Garitezi 7b80a9aa44 fix(aggregator): namespace aggregator ids with action type
Otherwise, actions of different types but same names will clash when starting the
aggregator supervision tree.
2024-05-09 16:02:11 -03:00
Andrew Mayorov 57dda70d2f
Merge pull request #12994 from keynslug/fix/sessds/log-levels
fix(sessds): use milder log level for regular error conditions
2024-05-09 18:34:54 +02:00
lafirest 23a1b18459
Merge pull request #12983 from emqx/feat/authn_hook
feat(events): add new hook && event `client.check_authn_complete`
2024-05-09 22:36:52 +08:00
Thales Macedo Garitezi 401f0fa84b Merge branch 'release-57' into sync-r57-m-20240508 2024-05-09 09:13:30 -03:00
firest 2bc014db69 fix(events): call `client.check_authn_complete` even if authentication fails 2024-05-09 18:15:32 +08:00
firest e3a59c4037 fix(sysk): fix that the syskeeper forwarding never reconnecting 2024-05-09 16:27:58 +08:00
Ilia Averianov a1aedee446
Merge pull request #12996 from savonarola/0508-fix-cursor-usage
fix(retainer): fix qlc cursor cleanup
2024-05-09 08:04:10 +03:00
firest d2ca4e9f11 chore: update change 2024-05-09 11:04:56 +08:00
ieQu1 07aa708894
test(ds): Refactor replication suite 2024-05-09 03:56:56 +02:00
zhongwencool 107d00adee
Merge pull request #12944 from zhongwencool/mqtt-utf8-strict-mode
fix: non-utf8 clientid connect event case crash if strict_mod=false
2024-05-09 09:16:10 +08:00
ieQu1 63e51fca66
test(ds): Use streams to fill the storage 2024-05-09 02:46:57 +02:00
ieQu1 a0a3977043
feat(ds): Assign latest timestamp deterministically 2024-05-08 23:17:57 +02:00
ieQu1 2236af84ba
feat(ds): two-stage storage commit on the storage level 2024-05-08 23:17:57 +02:00
ieQu1 f250f00f3f
chore: Bump snabbkaffe version to 1.0.10 2024-05-08 23:17:57 +02:00
ieQu1 1ddbbca90e
feat(ds): Allow incremental update of the LTS trie 2024-05-08 23:17:57 +02:00
ieQu1 68ca891f41
test(ds): Use streams to create traffic 2024-05-08 23:17:57 +02:00
Zaiming (Stone) Shi 018d79b498
Merge pull request #12993 from zmstone/0508-fix-update-listener-zone-from-dashboard
0508 fix update listener zone from dashboard
2024-05-08 22:03:10 +02:00
Thales Macedo Garitezi 55f27281b3
Merge pull request #12991 from thalesmg/refactor-mv-message-type-r57-20240508
refactor(message validation): rename `message_name` to `message_type`
2024-05-08 16:58:28 -03:00
Thales Macedo Garitezi d3905b6336
Merge pull request #12990 from thalesmg/fix-mv-conf-update-r57-20240508
fix(message validation): don't call `emqx_conf:update` during boot
2024-05-08 16:58:15 -03:00
Ilya Averyanov 57287f0722 fix(retainer): fix qlc cursor cleanup 2024-05-08 21:38:37 +03:00
Thales Macedo Garitezi 8d0574abf0
Merge pull request #12979 from thalesmg/fix-ps-monitor-topic-count-r57-20240506
fix(monitor api): count persistent routes and subscriptions
2024-05-08 15:09:16 -03:00
Andrew Mayorov ba66f2303a
Merge pull request #12995 from keynslug/feat/sessds/exclude-unreachable-servers
feat(dsrepl): avoid contacting unreachable ra servers
2024-05-08 19:19:46 +02:00
Andrew Mayorov d84c180ccb
feat(dsrepl): avoid contacting unreachable ra servers
Assuming estabilished Erlang distribution channel is a reliable way to
tell whether a remote node is reachable.
2024-05-08 18:12:13 +02:00
Andrew Mayorov 3e956e8711
fix(sessds): use milder log level for regular error conditions
Especially when such events are emitted in (potentially) tight loops,
i.e. pulling messages from iterators pointing to remote shards.
2024-05-08 17:40:08 +02:00
zmstone c75cee3c04 docs: add changelog for PR #12993 2024-05-08 17:04:53 +02:00
zmstone 9edbad5459 fix(listener_api): do not allow update listener with unknown zone name 2024-05-08 16:37:55 +02:00
Thales Macedo Garitezi d3bc32dc35 fix(message validation): don't call `emqx_conf:update` during boot
`load/0` and `unload/0` shouldn't call cluster operations.
2024-05-08 10:18:29 -03:00
Kjell Winblad 916168c755 fix: make rule engine unescape convert \a to the terminal alarm char
The rule engine unescape function should convert the escape sequence \a
to the alarm bell symbol (ASCII 7). This bug was created as it was
assumed that Erlang convert $\a to 7 but Erlang does not handle the \a
escape sequence and instead convert it to 97 (ASCII code for a).

Fixes:
https://emqx.atlassian.net/browse/EMQX-12313
2024-05-08 15:18:13 +02:00
Thales Macedo Garitezi 5172606032 refactor(message validation): rename `message_name` to `message_type`
On Product's behest, to make naming consistent with protobuf nomenclature.

https://protobuf.dev/programming-guides/proto3/#adding-types
2024-05-08 09:13:40 -03:00
zmstone 3a2ff34433 chore: add zone in listener config example 2024-05-08 11:43:10 +02:00
JimMoen f0a6fb0285
chore: bump dashboard vsn 2024-05-08 17:27:22 +08:00
JimMoen 25be9c2890
fix(plugin): use binary `NameVsn` to re-build plugin avsc serde 2024-05-08 15:43:54 +08:00
JimMoen 68c601ad72
fix(plugin): add a backup for the plugin config file 2024-05-08 15:43:53 +08:00
JianBo He 4403b4f5ce
Merge pull request #12976 from HJianBo/fix-duplicated-disconnect
Fix duplicated disconnect event
2024-05-08 14:43:19 +08:00
Kjell Winblad 72f68afbca
Merge pull request #12981 from kjellwinblad/kjell/fixup_trace_all_http_and_error
Make formatting of action result trace entries better
2024-05-08 06:10:03 +02:00
Thales Macedo Garitezi 1b2a204e38
Merge pull request #12988 from thalesmg/fix-ds-durable-response-r57-20240507
fix(clients mgmt api): set `durable` flag for DS sessions and subscriptions, add `clientid` to subscriptions
2024-05-07 18:04:33 -03:00
Thales Macedo Garitezi 0c7b221c42 fix(clients mgmt api): set `durable` flag for DS sessions and subscriptions 2024-05-07 14:55:50 -03:00
Kjell Winblad d5324e295f test: do cleanup in emqx_common_test_helpers:on_exit function
Thanks @thalesmg for the suggestion.
2024-05-07 18:18:18 +02:00
William Yang 6e5d04e9fa
Merge pull request #12977 from qzhuyan/port/william/5/partial-chain
chore: update doc for `partial_chain` and `verify_peer_ext_key_usage`
2024-05-07 16:42:10 +02:00
Thales Macedo Garitezi 02c58b67f0
Merge pull request #12986 from thalesmg/fix-mv-name-length-r57-20240507
fix(message validation): limit the length of validation name
2024-05-07 11:39:17 -03:00
Thales Macedo Garitezi 2989793f4c
Merge pull request #12980 from thalesmg/fix-ds-get-offline-client-stuff-r57-20240506
fix(mgmt clients api): hold channel info after client disconnects for display in API
2024-05-07 11:18:00 -03:00
Thales Macedo Garitezi d4d2b4c460
Merge pull request #12985 from thalesmg/fix-mv-cluster-metrics-r57-20240507
fix(message validation): apply config CRUD operations on whole cluster
2024-05-07 11:10:58 -03:00
Kjell Winblad 09ee7ec0e2 fix(rule tracing): make sure that recoverable errors are traced 2024-05-07 15:49:38 +02:00
SergeTupchiy ad9ace8d0a
Merge pull request #12984 from SergeTupchiy/EMQX-12255-handle-no-license-in-backup-restore
fix(emqx_license): don't crash if an imported backup file has no license config
2024-05-07 16:05:49 +03:00
Thales Macedo Garitezi 96bb6e7d88 fix(message validation): limit the length of validation name
Fixes https://emqx.atlassian.net/browse/EMQX-12299
2024-05-07 10:04:56 -03:00
Thales Macedo Garitezi 06f16d4ee0 fix(message validation): apply config CRUD operations on whole cluster
Fixes https://emqx.atlassian.net/browse/EMQX-12298
2024-05-07 09:45:50 -03:00
Thales Macedo Garitezi 6d6eb42fa3 fix(mgmt clients api): hold channel info after client disconnects for display in api
Fixes https://emqx.atlassian.net/browse/EMQX-12266
2024-05-07 09:22:33 -03:00
Serge Tupchii b869488d35 fix(emqx_license): don't crash if an imported backup file has no license config 2024-05-07 13:48:04 +03:00
zhongwencool 78095ef9bc chore: changelog 2024-05-07 17:04:58 +08:00
zhongwencool a0bf06caba chore: add test case for non-utf8 topic 2024-05-07 17:02:45 +08:00
JianBo He c947455b15 chore: add changes 2024-05-07 16:27:34 +08:00
firest f641d0b2b7 feat(events): add new hook && event `client.check_authn_complete` 2024-05-07 16:24:31 +08:00
Kjell Winblad feecc36607 fix(rule tracing): clean up error tuple in the action_failed trace 2024-05-07 09:13:55 +02:00
JianBo He 1642b06bf9 test: add tests 2024-05-07 10:30:53 +08:00
Thales Macedo Garitezi 28355a4cfc fix(monitor api): count persistent routes and subscriptions
Fixes https://emqx.atlassian.net/browse/EMQX-12267
2024-05-06 16:51:31 -03:00
Zaiming (Stone) Shi 93e31d088a
Merge pull request #12978 from JimMoen/fix-typo
chore: fix typo
2024-05-06 21:28:51 +02:00
Thales Macedo Garitezi 83a0206aaa
Merge pull request #12973 from thalesmg/shared-bridge-aggregator-r57-20240503
refactor: extract blob aggregator logic to separate application
2024-05-06 16:19:21 -03:00
William Yang 28b17a2562 chore: fix nit for spellcheck 2024-05-06 21:02:33 +02:00
Kjell Winblad ca88f5731b fix(rule tracing): format result traces in a more structured way 2024-05-06 17:33:59 +02:00
William Yang 01467246fc docs: Apply suggestions from code review
Co-authored-by: Zaiming (Stone) Shi <zmstone@gmail.com>
2024-05-06 17:08:55 +02:00
William Yang c3f8ba5762 chore: update doc for `partial_chain` and `verify_peer_ext_key_usage` 2024-05-06 16:03:52 +02:00
Thales Macedo Garitezi cd4aaf663b docs: briefly describe delivery callbacks 2024-05-06 10:00:10 -03:00
Thales Macedo Garitezi e6b1dfb095 refactor: improve error 2024-05-06 09:53:49 -03:00
Thales Macedo Garitezi 793cc4df2c fix: add fully qualified calls to enable hot beam reloads 2024-05-06 09:52:31 -03:00
Thales Macedo Garitezi edcb750d9f fix: remove unused dependency 2024-05-06 09:51:32 -03:00
Thales Macedo Garitezi 36542a4b1d docs: bump copyright years 2024-05-06 09:50:12 -03:00
Ilia Averianov e19222fc0d
Merge pull request #12971 from savonarola/0502-fix-url-parse
fix(auth,http): improve URI handling
2024-05-06 13:41:10 +03:00
JimMoen 1df2d837ee
chore: fix typo 2024-05-06 17:37:32 +08:00
ieQu1 3642bcd1b6
docs(ds): Fix comment for the builtin DS metrics 2024-05-06 11:21:32 +02:00
ieQu1 b2a633aca1
fix(ds): Use leader's clock for computing LTS safe cutoff time 2024-05-06 11:21:32 +02:00
ieQu1 1ff2e02fd9
feat(ds): Pass current time to the storage layer via argument 2024-05-06 11:21:32 +02:00
ieQu1 8ac9700aab
feat(ds): Add an API for DB-global variables 2024-05-06 11:21:32 +02:00
ieQu1 86d45522e3
fix(dsrepl): Don't reverse elements of batches 2024-05-06 11:21:32 +02:00
ieQu1 bcfa7b2209
fix(ds): Destroy LTS tries when the generation is dropped 2024-05-06 11:21:32 +02:00
ieQu1 9999ccd36c
feat(ds): Ignore safe cutoff time for streams without varying levels 2024-05-06 11:21:32 +02:00
Ilya Averyanov 31026d51f7 chore(auth,http): cache REs for parsing URIs 2024-05-06 11:46:18 +03:00
JianBo He b320b20c7b fix(mqtt): disconnected event should not be sent twice 2024-05-06 16:17:02 +08:00
JianBo He cabe2ae100 chore: fix dialyzer warning 2024-05-06 14:58:27 +08:00
JianBo He d2b6e41cd1 chore(stomp): parse \n as heartbeat frame 2024-05-06 14:39:41 +08:00
Ilya Averyanov 3b655f56cb fix(auth,http): improve URI handling 2024-05-04 09:47:13 +03:00
Zaiming (Stone) Shi e7f0c83406
Merge pull request #12970 from zmstone/0503-refactor-dashboard-listener
refactor: simplify https listener config for dashboard
2024-05-04 08:38:29 +02:00
Zaiming (Stone) Shi c5d8659f35
Merge pull request #12972 from zmstone/0503-unhide-default-dashboard-username-password
chore: unhide dashboard default_password config
2024-05-04 08:36:32 +02:00
Thales Macedo Garitezi 32493e395c refactor: avoid passing record down to template rendering function 2024-05-03 17:43:30 -03:00
Thales Macedo Garitezi 157e2c2535 refactor: make api more generic 2024-05-03 17:25:02 -03:00
Thales Macedo Garitezi a6508e2fca refactor: use better names
Co-authored-by: Andrew Mayorov <encube.ul@gmail.com>
2024-05-03 17:04:09 -03:00
Thales Macedo Garitezi d61f4078e2 refactor: extract blob aggregator logic to separate application
This will allow other bridges to share the same aggregation logic as S3 aggregated action.
2024-05-03 14:35:58 -03:00
zmstone 4d3156b5ed chore: unhide dashboard default_username and default_password config 2024-05-03 18:35:49 +02:00
Thales Macedo Garitezi 3818b75188
Merge pull request #12959 from thalesmg/kprodu-connector-hc-m-20240429
feat(kafka producer): add health check topic option
2024-05-03 12:48:48 -03:00
zmstone 3c5c76fcfc refactor: simplify https listener config for dashboard 2024-05-03 16:45:40 +02:00
Thales Macedo Garitezi 6f3da6b131 feat(kafka producer): add health check topic option
Fixes https://emqx.atlassian.net/browse/EMQX-12241

This allows more accurate health checking for Kafka Producers.  Without a topic, it's not
possible to actually probe the connection to partition leaders, so the connector might not
be reported as `disconnected` without testing a concrete topic.
2024-05-02 17:07:44 -03:00
Thales Macedo Garitezi 28cdce7464
Merge pull request #12964 from thalesmg/ci-cron-pkgs-20240502
ci(cron packages): use unique upload names for different branches
2024-05-02 16:19:11 -03:00
Thales Macedo Garitezi 5b39b9c11f ci(cron packages): use unique upload names for different branches 2024-05-02 15:31:57 -03:00
Thales Macedo Garitezi c71f73924b
Merge pull request #12961 from thalesmg/kconsu-custom-group-id-m-20240430
feat(kafka consumer): allow custom group id
2024-05-02 14:37:42 -03:00
Ivan Dyachkov 98dee03773
Merge pull request #12963 from id/0502-sync-release-57
sync release-57
2024-05-02 18:33:28 +02:00
Ivan Dyachkov cc577e636d Merge remote-tracking branch 'upstream/release-57' into 0502-sync-release-57 2024-05-02 17:06:18 +02:00
Thales Macedo Garitezi 905d04f1c3 docs: improve descriptions 2024-05-02 11:19:14 -03:00
Thales Macedo Garitezi eb113fa578 fix: add non-empty validator 2024-05-02 11:19:00 -03:00
William Yang 8f780ae8bc
Merge pull request #12955 from qzhuyan/port/william/5/partial-chain
port: TLS partial chain
2024-05-02 15:34:25 +02:00
Thales Macedo Garitezi 3942b371d7 feat(kafka consumer): allow custom group id
Fixes https://emqx.atlassian.net/browse/EMQX-12273
Fixes EMQX-12273

When consuming messages in Kafka in Alibaba Cloud, the group needs to be configured in
advance, and then the consumer can use the group to consume messages. Automatic group
creation is generally not allowed online.
2024-05-02 08:59:40 -03:00
William Yang 1a4a4bb3a5 chore: fix nit 2024-05-02 10:13:57 +02:00
Thales Macedo Garitezi 14ef0b1e51 feat(kafka consumer): allow custom group id
Fixes https://emqx.atlassian.net/browse/EMQX-12273
Fixes EMQX-12273

When consuming messages in Kafka in Alibaba Cloud, the group needs to be configured in
advance, and then the consumer can use the group to consume messages. Automatic group
creation is generally not allowed online.
2024-05-01 13:53:29 -03:00
Thales Macedo Garitezi 437e7968b1
Merge pull request #12960 from thalesmg/sync-r57-m-20240430
sync `release-57` to `master`
2024-05-01 13:52:16 -03:00
Thales Macedo Garitezi 42cb17360e Merge branch 'release-57' into sync-r57-m-20240430 2024-04-30 14:42:22 -03:00
William Yang fb30207ef3 chore: fix test 2024-04-30 16:41:46 +02:00
William Yang 337c230e79 feat(partial_chain): gateway support 2024-04-30 16:41:26 +02:00
William Yang 3a674f44f1 chore: lock mimerl 2024-04-30 10:27:02 +02:00
Kjell Winblad 7b638a5829 style: fix spelling mistake (thanks @savonarola) 2024-04-30 09:28:12 +02:00
William Yang 70ffd77f99 chore(TLS-chain-test): update for OTP 26 2024-04-30 09:05:51 +02:00
William Yang 03b0935564 chore: add changelog 2024-04-30 06:25:03 +02:00
William Yang 650cf4b27e test(partial_chain): update tcs for OTP-25 2024-04-30 06:25:03 +02:00
William Yang 43ad665dcf fix(test): tls_verify_partial_chain 2024-04-30 06:25:03 +02:00
William Yang a29a43e5fc fix(listener): remove partial_chain in wss opts 2024-04-30 06:25:03 +02:00
William Yang 4e9c1ec0c9 chore: happy elvis 2024-04-30 06:25:03 +02:00
William Yang 8eb463c58d feat(tls): update schema for TLS keyusage 2024-04-30 06:25:03 +02:00
William Yang 90430fa66d fix(tls): undefined keyusage 2024-04-30 06:25:03 +02:00
William Yang eb1ab9adfe test(tls): verify peer keyusage 2024-04-30 06:25:03 +02:00
William Yang 8bc3a86f63 feat(config): partial_chain 2024-04-30 06:25:03 +02:00
William Yang fa4357ce89 test: port listener tls partial_chain 2024-04-30 06:25:03 +02:00
William Yang 0b95a08d32 feat(tls): port partial_chain, part 1 2024-04-30 06:25:03 +02:00
zhongwencool ef9a63ae17 fix: non-utf8 clientid connect event case crash if strict_mod=false 2024-04-29 14:43:29 +08:00
Ilia Averianov 002dc8541b
Merge pull request #12936 from savonarola/0426-improve-authz-rule-typespecs
chore(authz): improve and clarify types
2024-04-26 19:43:41 +03:00
Kjell Winblad db48a977bb test(mongodb authn, authz): add test cases for use_legacy_protocol
This commit adds test cases that check that the authn and authz modules
for MongoDB support the use_legacy_protocol configuration option.

Fixes:
https://emqx.atlassian.net/browse/EMQX-12245
2024-04-26 12:41:50 +02:00
Ilya Averyanov aaf57ecfbc chore(authz): improve and clarify types 2024-04-26 12:09:18 +03:00
Ilia Averianov a0e0a27f87
Merge pull request #12418 from savonarola/0129-fix-auth-claim-schema
feat(jwt_auth): improve verify_claims handling and docs
2024-04-25 19:05:13 +03:00
chengshq 75dab4dff0 fix: STOMP heartbeat 2024-04-25 23:33:15 +08:00
Ilya Averyanov 407b0cd0ca feat(jwt_auth): improve verify_claims handling and docs 2024-04-25 17:49:29 +03:00
Ilia Averianov c42583550d
Merge pull request #12514 from savonarola/0214-fix-ft-responses
fix(ft): report ft assemble status from a dedicated process
2024-04-25 15:10:26 +03:00
Ilya Averyanov 05f544495e fix(ft): report ft assemble status from a dedicated process
Previously, the status was monitored by the channel itself.
If channel disconnected before the assemble was completed,
the status message was lost (not sent to the resonse topic)
2024-04-24 18:16:28 +03:00
1279 changed files with 66564 additions and 12480 deletions

View File

@ -0,0 +1,24 @@
version: '3.9'
services:
azurite:
container_name: azurite
image: mcr.microsoft.com/azure-storage/azurite:3.30.0
restart: always
expose:
- "10000"
# ports:
# - "10000:10000"
networks:
- emqx_bridge
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:10000"]
interval: 30s
timeout: 5s
retries: 4
command:
- azurite-blob
- "--blobHost"
- 0.0.0.0
- "-d"
- debug.log

View File

@ -0,0 +1,30 @@
version: '3.9'
services:
couchbase:
container_name: couchbase
hostname: couchbase
image: ghcr.io/emqx/couchbase:1.0.0
restart: always
expose:
- 8091-8093
# ports:
# - "8091-8093:8091-8093"
networks:
- emqx_bridge
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8093/admin/ping"]
interval: 30s
timeout: 5s
retries: 4
environment:
- CLUSTER=localhost
- USER=admin
- PASS=public
- PORT=8091
- RAMSIZEMB=2048
- RAMSIZEINDEXMB=512
- RAMSIZEFTSMB=512
- BUCKETS=mqtt
- BUCKETSIZES=100
- AUTOREBALANCE=true

View File

@ -18,7 +18,7 @@ services:
- /tmp/emqx-ci/emqx-shared-secret:/var/lib/secret - /tmp/emqx-ci/emqx-shared-secret:/var/lib/secret
kdc: kdc:
hostname: kdc.emqx.net hostname: kdc.emqx.net
image: ghcr.io/emqx/emqx-builder/5.3-5:1.15.7-26.2.1-2-ubuntu22.04 image: ghcr.io/emqx/emqx-builder/5.3-9:1.15.7-26.2.5-3-ubuntu22.04
container_name: kdc.emqx.net container_name: kdc.emqx.net
expose: expose:
- 88 # kdc - 88 # kdc

View File

@ -10,7 +10,7 @@ services:
nofile: 1024 nofile: 1024
image: openldap image: openldap
#ports: #ports:
# - 389:389 # - "389:389"
volumes: volumes:
- ./certs/ca.crt:/etc/certs/ca.crt - ./certs/ca.crt:/etc/certs/ca.crt
restart: always restart: always

View File

@ -0,0 +1,41 @@
version: '3.9'
services:
mqnamesrvssl:
image: apache/rocketmq:4.9.4
container_name: rocketmq_namesrv_ssl
# ports:
# - 9876:9876
volumes:
- ./rocketmq/logs_ssl:/opt/logs
- ./rocketmq/store_ssl:/opt/store
environment:
JAVA_OPT: "-Dtls.server.mode=enforcing"
command: ./mqnamesrv
networks:
- emqx_bridge
mqbrokerssl:
image: apache/rocketmq:4.9.4
container_name: rocketmq_broker_ssl
# ports:
# - 10909:10909
# - 10911:10911
volumes:
- ./rocketmq/logs_ssl:/opt/logs
- ./rocketmq/store_ssl:/opt/store
- ./rocketmq/conf_ssl/broker.conf:/etc/rocketmq/broker.conf
- ./rocketmq/conf_ssl/plain_acl.yml:/home/rocketmq/rocketmq-4.9.4/conf/plain_acl.yml
environment:
NAMESRV_ADDR: "rocketmq_namesrv_ssl:9876"
JAVA_OPTS: " -Duser.home=/opt -Drocketmq.broker.diskSpaceWarningLevelRatio=0.99"
JAVA_OPT_EXT: "-server -Xms512m -Xmx512m -Xmn512m -Dtls.server.mode=enforcing"
command: ./mqbroker -c /etc/rocketmq/broker.conf
depends_on:
- mqnamesrvssl
networks:
- emqx_bridge
networks:
emqx_bridge:
driver: bridge

View File

@ -3,7 +3,7 @@ version: '3.9'
services: services:
erlang: erlang:
container_name: erlang container_name: erlang
image: ${DOCKER_CT_RUNNER_IMAGE:-ghcr.io/emqx/emqx-builder/5.3-5:1.15.7-26.2.1-2-ubuntu22.04} image: ${DOCKER_CT_RUNNER_IMAGE:-ghcr.io/emqx/emqx-builder/5.3-9:1.15.7-26.2.5-3-ubuntu22.04}
env_file: env_file:
- credentials.env - credentials.env
- conf.env - conf.env

View File

@ -49,6 +49,9 @@ echo "+++++++ Creating Kafka Topics ++++++++"
# there seem to be a race condition when creating the topics (too early) # there seem to be a race condition when creating the topics (too early)
env KAFKA_CREATE_TOPICS="$KAFKA_CREATE_TOPICS_NG" KAFKA_PORT="$PORT1" create-topics.sh env KAFKA_CREATE_TOPICS="$KAFKA_CREATE_TOPICS_NG" KAFKA_PORT="$PORT1" create-topics.sh
# create a topic with max.message.bytes=100
/opt/kafka/bin/kafka-topics.sh --create --bootstrap-server "${SERVER}:${PORT1}" --topic max-100-bytes --partitions 1 --replication-factor 1 --config max.message.bytes=100
echo "+++++++ Wait until Kafka ports are down ++++++++" echo "+++++++ Wait until Kafka ports are down ++++++++"
bash -c 'while printf "" 2>>/dev/null >>/dev/tcp/$0/$1; do sleep 1; done' $SERVER $PORT1 bash -c 'while printf "" 2>>/dev/null >>/dev/tcp/$0/$1; do sleep 1; done' $SERVER $PORT1

View File

@ -0,0 +1,61 @@
# LDAP authentication
To run manual tests with the default docker-compose files.
Expose openldap container port by uncommenting the `ports` config in `docker-compose-ldap.yaml `
To start openldap:
```
docker-compose -f ./.ci/docker-compose-file/docker-compose.yaml -f ./.ci/docker-compose-file/docker-compose-ldap.yaml up -docker
```
## LDAP database
LDAP database is populated from below files:
```
apps/emqx_ldap/test/data/emqx.io.ldif /usr/local/etc/openldap/schema/emqx.io.ldif
apps/emqx_ldap/test/data/emqx.schema /usr/local/etc/openldap/schema/emqx.schema
```
## Minimal EMQX config
```
authentication = [
{
backend = ldap
base_dn = "uid=${username},ou=testdevice,dc=emqx,dc=io"
filter = "(& (objectClass=mqttUser) (uid=${username}))"
mechanism = password_based
method {
is_superuser_attribute = isSuperuser
password_attribute = userPassword
type = hash
}
password = public
pool_size = 8
query_timeout = "5s"
request_timeout = "10s"
server = "localhost:1389"
username = "cn=root,dc=emqx,dc=io"
}
]
```
## Example ldapsearch command
```
ldapsearch -x -H ldap://localhost:389 -D "cn=root,dc=emqx,dc=io" -W -b "uid=mqttuser0007,ou=testdevice,dc=emqx,dc=io" "(&(objectClass=mqttUser)(uid=mqttuser0007))"
```
## Example mqttx command
The client password hashes are generated from their username.
```
# disabled user
mqttx pub -t 't/1' -h localhost -p 1883 -m x -u mqttuser0006 -P mqttuser0006
# enabled super-user
mqttx pub -t 't/1' -h localhost -p 1883 -m x -u mqttuser0007 -P mqttuser0007
```

View File

@ -0,0 +1,24 @@
brokerClusterName=DefaultClusterSSL
brokerName=broker-a
brokerId=0
brokerIP1=rocketmq_broker_ssl
defaultTopicQueueNums=4
autoCreateTopicEnable=true
autoCreateSubscriptionGroup=true
listenPort=10911
deleteWhen=04
fileReservedTime=120
mapedFileSizeCommitLog=1073741824
mapedFileSizeConsumeQueue=300000
diskMaxUsedSpaceRatio=100
maxMessageSize=65536
brokerRole=ASYNC_MASTER
flushDiskType=ASYNC_FLUSH
aclEnable=true

View File

@ -0,0 +1,12 @@
globalWhiteRemoteAddresses:
accounts:
- accessKey: RocketMQ
secretKey: 12345678
whiteRemoteAddress:
admin: false
defaultTopicPerm: DENY
defaultGroupPerm: PUB|SUB
topicPerms:
- TopicTest=PUB|SUB
- Topic2=PUB|SUB

View File

@ -215,5 +215,17 @@
"listen": "0.0.0.0:9200", "listen": "0.0.0.0:9200",
"upstream": "elasticsearch:9200", "upstream": "elasticsearch:9200",
"enabled": true "enabled": true
},
{
"name": "azurite_plain",
"listen": "0.0.0.0:10000",
"upstream": "azurite:10000",
"enabled": true
},
{
"name": "couchbase",
"listen": "0.0.0.0:8093",
"upstream": "couchbase:8093",
"enabled": true
} }
] ]

View File

@ -1,18 +1,18 @@
%% -*- mode: erlang -*- %% -*- mode: erlang -*-
{application, http_server, {application, http_server, [
[{description, "An HTTP server application"}, {description, "An HTTP server application"},
{vsn, "0.2.0"}, {vsn, "0.2.0"},
{registered, []}, {registered, []},
% {mod, {http_server_app, []}}, % {mod, {http_server_app, []}},
{modules, []}, {modules, []},
{applications, {applications, [
[kernel, kernel,
stdlib, stdlib,
minirest minirest
]}, ]},
{env,[]}, {env, []},
{modules, []}, {modules, []},
{licenses, ["Apache 2.0"]}, {licenses, ["Apache 2.0"]},
{links, []} {links, []}
]}. ]}.

View File

@ -33,7 +33,7 @@ runs:
HOMEBREW_NO_INSTALL_UPGRADE: 1 HOMEBREW_NO_INSTALL_UPGRADE: 1
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1 HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
run: | run: |
brew install curl zip unzip coreutils openssl@1.1 brew install curl zip unzip coreutils openssl@1.1 unixodbc
echo "/usr/local/opt/bison/bin" >> $GITHUB_PATH echo "/usr/local/opt/bison/bin" >> $GITHUB_PATH
echo "/usr/local/bin" >> $GITHUB_PATH echo "/usr/local/bin" >> $GITHUB_PATH
echo "emqx_name=${emqx_name}" >> $GITHUB_OUTPUT echo "emqx_name=${emqx_name}" >> $GITHUB_OUTPUT
@ -51,12 +51,12 @@ runs:
echo "SELF_HOSTED=false" >> $GITHUB_OUTPUT echo "SELF_HOSTED=false" >> $GITHUB_OUTPUT
;; ;;
esac esac
- uses: actions/cache@ab5e6d0c87105b4c9c2047343972218f562e4319 # v4.0.1 - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
id: cache id: cache
if: steps.prepare.outputs.SELF_HOSTED != 'true' if: steps.prepare.outputs.SELF_HOSTED != 'true'
with: with:
path: ${{ steps.prepare.outputs.OTP_INSTALL_PATH }} path: ${{ steps.prepare.outputs.OTP_INSTALL_PATH }}
key: otp-install-${{ inputs.otp }}-${{ inputs.os }}-static-ssl-disable-hipe-disable-jit key: otp-install-${{ inputs.otp }}-${{ inputs.os }}-static-ssl-disable-hipe-disable-jit-20240524-1
- name: build erlang - name: build erlang
if: steps.cache.outputs.cache-hit != 'true' if: steps.cache.outputs.cache-hit != 'true'
shell: bash shell: bash
@ -80,9 +80,10 @@ runs:
git clone --depth 1 --branch OTP-${{ inputs.otp }} https://github.com/emqx/otp.git "$OTP_SOURCE_PATH" git clone --depth 1 --branch OTP-${{ inputs.otp }} https://github.com/emqx/otp.git "$OTP_SOURCE_PATH"
cd "$OTP_SOURCE_PATH" cd "$OTP_SOURCE_PATH"
if [ "$(arch)" = arm64 ]; then if [ "$(arch)" = arm64 ]; then
export CFLAGS="-O2 -g -I$(brew --prefix unixodbc)/include" ODBCHOME="$(brew --prefix unixodbc)"
export LDFLAGS="-L$(brew --prefix unixodbc)/lib" export CFLAGS="-O2 -g -I${ODBCHOME}/include"
WITH_ODBC="--with-odbc=$(brew --prefix unixodbc)" export LDFLAGS="-L${ODBCHOME}/lib"
WITH_ODBC="--with-odbc=${ODBCHOME}"
else else
WITH_ODBC="" WITH_ODBC=""
fi fi

View File

@ -1,24 +1,8 @@
name: 'Prepare jmeter' name: 'Prepare jmeter'
inputs:
version-emqx:
required: true
type: string
runs: runs:
using: composite using: composite
steps: steps:
- uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4
with:
name: emqx-docker
path: /tmp
- name: load docker image
shell: bash
env:
PKG_VSN: ${{ inputs.version-emqx }}
run: |
EMQX_DOCKER_IMAGE_TAG=$(docker load < /tmp/emqx-docker-${PKG_VSN}.tar.gz | sed 's/Loaded image: //g')
echo "_EMQX_DOCKER_IMAGE_TAG=$EMQX_DOCKER_IMAGE_TAG" >> $GITHUB_ENV
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
with: with:
repository: emqx/emqx-fvt repository: emqx/emqx-fvt

1
.github/workflows/.zipignore2 vendored Normal file
View File

@ -0,0 +1 @@
*/.github/*

View File

@ -11,29 +11,48 @@ on:
ref: ref:
required: false required: false
defaults:
run:
shell: bash
env: env:
IS_CI: "yes" IS_CI: "yes"
permissions:
contents: read
jobs: jobs:
init:
runs-on: ubuntu-22.04
outputs:
BUILDER_VSN: ${{ steps.env.outputs.BUILDER_VSN }}
OTP_VSN: ${{ steps.env.outputs.OTP_VSN }}
ELIXIR_VSN: ${{ steps.env.outputs.ELIXIR_VSN }}
BUILDER: ${{ steps.env.outputs.BUILDER }}
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
ref: ${{ github.event.inputs.ref }}
- name: Set up environment
id: env
run: |
source ./env.sh
echo "BUILDER_VSN=$EMQX_BUILDER_VSN" | tee -a "$GITHUB_OUTPUT"
echo "OTP_VSN=$OTP_VSN" | tee -a "$GITHUB_OUTPUT"
echo "ELIXIR_VSN=$ELIXIR_VSN" | tee -a "$GITHUB_OUTPUT"
echo "BUILDER=$EMQX_BUILDER" | tee -a "$GITHUB_OUTPUT"
sanity-checks: sanity-checks:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
container: "ghcr.io/emqx/emqx-builder/5.3-5:1.15.7-26.2.1-2-ubuntu22.04" needs: init
container: ${{ needs.init.outputs.BUILDER }}
outputs: outputs:
ct-matrix: ${{ steps.matrix.outputs.ct-matrix }} ct-matrix: ${{ steps.matrix.outputs.ct-matrix }}
ct-host: ${{ steps.matrix.outputs.ct-host }} ct-host: ${{ steps.matrix.outputs.ct-host }}
ct-docker: ${{ steps.matrix.outputs.ct-docker }} ct-docker: ${{ steps.matrix.outputs.ct-docker }}
version-emqx: ${{ steps.matrix.outputs.version-emqx }}
version-emqx-enterprise: ${{ steps.matrix.outputs.version-emqx-enterprise }} permissions:
builder: "ghcr.io/emqx/emqx-builder/5.3-5:1.15.7-26.2.1-2-ubuntu22.04" contents: read
builder_vsn: "5.3-5"
otp_vsn: "26.2.1-2"
elixir_vsn: "1.15.7"
steps: steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
ref: ${{ github.event.inputs.ref }} ref: ${{ github.event.inputs.ref }}
fetch-depth: 0 fetch-depth: 0
@ -78,7 +97,8 @@ jobs:
MIX_ENV: emqx-enterprise MIX_ENV: emqx-enterprise
PROFILE: emqx-enterprise PROFILE: emqx-enterprise
run: | run: |
mix local.hex --force --if-missing && mix local.rebar --force --if-missing # mix local.hex --force --if-missing && mix local.rebar --force --if-missing
mix local.hex 2.0.6 --force --if-missing && mix local.rebar --force --if-missing
- name: Check formatting - name: Check formatting
env: env:
MIX_ENV: emqx-enterprise MIX_ENV: emqx-enterprise
@ -91,35 +111,20 @@ jobs:
- name: Generate CT Matrix - name: Generate CT Matrix
id: matrix id: matrix
run: | run: |
APPS="$(./scripts/find-apps.sh --ci)" MATRIX="$(./scripts/find-apps.sh --ci)"
MATRIX="$(echo "${APPS}" | jq -c '
[
(.[] | select(.profile == "emqx") | . + {
builder: "5.3-5",
otp: "26.2.1-2",
elixir: "1.15.7"
}),
(.[] | select(.profile == "emqx-enterprise") | . + {
builder: "5.3-5",
otp: ["26.2.1-2"][],
elixir: "1.15.7"
})
]
')"
echo "${MATRIX}" | jq echo "${MATRIX}" | jq
CT_MATRIX="$(echo "${MATRIX}" | jq -c 'map({profile, builder, otp, elixir}) | unique')" CT_MATRIX="$(echo "${MATRIX}" | jq -c 'map({profile}) | unique')"
CT_HOST="$(echo "${MATRIX}" | jq -c 'map(select(.runner == "host"))')" CT_HOST="$(echo "${MATRIX}" | jq -c 'map(select(.runner == "host"))')"
CT_DOCKER="$(echo "${MATRIX}" | jq -c 'map(select(.runner == "docker"))')" CT_DOCKER="$(echo "${MATRIX}" | jq -c 'map(select(.runner == "docker"))')"
echo "ct-matrix=${CT_MATRIX}" | tee -a $GITHUB_OUTPUT echo "ct-matrix=${CT_MATRIX}" | tee -a $GITHUB_OUTPUT
echo "ct-host=${CT_HOST}" | tee -a $GITHUB_OUTPUT echo "ct-host=${CT_HOST}" | tee -a $GITHUB_OUTPUT
echo "ct-docker=${CT_DOCKER}" | tee -a $GITHUB_OUTPUT echo "ct-docker=${CT_DOCKER}" | tee -a $GITHUB_OUTPUT
echo "version-emqx=$(./pkg-vsn.sh emqx)" | tee -a $GITHUB_OUTPUT
echo "version-emqx-enterprise=$(./pkg-vsn.sh emqx-enterprise)" | tee -a $GITHUB_OUTPUT
compile: compile:
runs-on: ${{ endsWith(github.repository, '/emqx') && 'ubuntu-22.04' || fromJSON('["self-hosted","ephemeral-xl","linux","x64"]') }} runs-on: ${{ endsWith(github.repository, '/emqx') && 'ubuntu-22.04' || fromJSON('["self-hosted","ephemeral-xl","linux","x64"]') }}
container: ${{ needs.sanity-checks.outputs.builder }} container: ${{ needs.init.outputs.BUILDER }}
needs: needs:
- init
- sanity-checks - sanity-checks
strategy: strategy:
matrix: matrix:
@ -127,8 +132,11 @@ jobs:
- emqx - emqx
- emqx-enterprise - emqx-enterprise
permissions:
contents: read
steps: steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Work around https://github.com/actions/checkout/issues/766 - name: Work around https://github.com/actions/checkout/issues/766
@ -144,7 +152,7 @@ jobs:
echo "PROFILE=${PROFILE}" | tee -a .env echo "PROFILE=${PROFILE}" | tee -a .env
echo "PKG_VSN=$(./pkg-vsn.sh ${PROFILE})" | tee -a .env echo "PKG_VSN=$(./pkg-vsn.sh ${PROFILE})" | tee -a .env
zip -ryq -x@.github/workflows/.zipignore $PROFILE.zip . zip -ryq -x@.github/workflows/.zipignore $PROFILE.zip .
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
with: with:
name: ${{ matrix.profile }} name: ${{ matrix.profile }}
path: ${{ matrix.profile }}.zip path: ${{ matrix.profile }}.zip
@ -152,53 +160,47 @@ jobs:
run_emqx_app_tests: run_emqx_app_tests:
needs: needs:
- init
- sanity-checks - sanity-checks
- compile - compile
uses: ./.github/workflows/run_emqx_app_tests.yaml uses: ./.github/workflows/run_emqx_app_tests.yaml
with: with:
builder: ${{ needs.sanity-checks.outputs.builder }} builder: ${{ needs.init.outputs.BUILDER }}
before_ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event.before }} before_ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event.before }}
after_ref: ${{ github.sha }} after_ref: ${{ github.sha }}
run_test_cases: run_test_cases:
needs: needs:
- init
- sanity-checks - sanity-checks
- compile - compile
uses: ./.github/workflows/run_test_cases.yaml uses: ./.github/workflows/run_test_cases.yaml
with: with:
builder: ${{ needs.sanity-checks.outputs.builder }} builder: ${{ needs.init.outputs.BUILDER }}
ct-matrix: ${{ needs.sanity-checks.outputs.ct-matrix }} ct-matrix: ${{ needs.sanity-checks.outputs.ct-matrix }}
ct-host: ${{ needs.sanity-checks.outputs.ct-host }} ct-host: ${{ needs.sanity-checks.outputs.ct-host }}
ct-docker: ${{ needs.sanity-checks.outputs.ct-docker }} ct-docker: ${{ needs.sanity-checks.outputs.ct-docker }}
static_checks: static_checks:
needs: needs:
- init
- sanity-checks - sanity-checks
- compile - compile
uses: ./.github/workflows/static_checks.yaml uses: ./.github/workflows/static_checks.yaml
with: with:
builder: ${{ needs.sanity-checks.outputs.builder }} builder: ${{ needs.init.outputs.BUILDER }}
ct-matrix: ${{ needs.sanity-checks.outputs.ct-matrix }} ct-matrix: ${{ needs.sanity-checks.outputs.ct-matrix }}
build_slim_packages: build_slim_packages:
needs: needs:
- sanity-checks - sanity-checks
uses: ./.github/workflows/build_slim_packages.yaml uses: ./.github/workflows/build_slim_packages.yaml
with:
builder: ${{ needs.sanity-checks.outputs.builder }}
builder_vsn: ${{ needs.sanity-checks.outputs.builder_vsn }}
otp_vsn: ${{ needs.sanity-checks.outputs.otp_vsn }}
elixir_vsn: ${{ needs.sanity-checks.outputs.elixir_vsn }}
build_docker_for_test: build_docker_for_test:
needs: needs:
- init
- sanity-checks - sanity-checks
uses: ./.github/workflows/build_docker_for_test.yaml uses: ./.github/workflows/build_docker_for_test.yaml
with:
otp_vsn: ${{ needs.sanity-checks.outputs.otp_vsn }}
elixir_vsn: ${{ needs.sanity-checks.outputs.elixir_vsn }}
version-emqx: ${{ needs.sanity-checks.outputs.version-emqx }}
version-emqx-enterprise: ${{ needs.sanity-checks.outputs.version-emqx-enterprise }}
spellcheck: spellcheck:
needs: needs:
@ -208,41 +210,35 @@ jobs:
run_conf_tests: run_conf_tests:
needs: needs:
- init
- sanity-checks - sanity-checks
- compile - compile
uses: ./.github/workflows/run_conf_tests.yaml uses: ./.github/workflows/run_conf_tests.yaml
with: with:
builder: ${{ needs.sanity-checks.outputs.builder }} builder: ${{ needs.init.outputs.BUILDER }}
check_deps_integrity: check_deps_integrity:
needs: needs:
- init
- sanity-checks - sanity-checks
uses: ./.github/workflows/check_deps_integrity.yaml uses: ./.github/workflows/check_deps_integrity.yaml
with: with:
builder: ${{ needs.sanity-checks.outputs.builder }} builder: ${{ needs.init.outputs.BUILDER }}
run_jmeter_tests: run_jmeter_tests:
needs: needs:
- sanity-checks - sanity-checks
- build_docker_for_test - build_docker_for_test
uses: ./.github/workflows/run_jmeter_tests.yaml uses: ./.github/workflows/run_jmeter_tests.yaml
with:
version-emqx: ${{ needs.sanity-checks.outputs.version-emqx }}
run_docker_tests: run_docker_tests:
needs: needs:
- sanity-checks - sanity-checks
- build_docker_for_test - build_docker_for_test
uses: ./.github/workflows/run_docker_tests.yaml uses: ./.github/workflows/run_docker_tests.yaml
with:
version-emqx: ${{ needs.sanity-checks.outputs.version-emqx }}
version-emqx-enterprise: ${{ needs.sanity-checks.outputs.version-emqx-enterprise }}
run_helm_tests: run_helm_tests:
needs: needs:
- sanity-checks - sanity-checks
- build_docker_for_test - build_docker_for_test
uses: ./.github/workflows/run_helm_tests.yaml uses: ./.github/workflows/run_helm_tests.yaml
with:
version-emqx: ${{ needs.sanity-checks.outputs.version-emqx }}
version-emqx-enterprise: ${{ needs.sanity-checks.outputs.version-emqx-enterprise }}

View File

@ -8,22 +8,51 @@ on:
push: push:
tags: tags:
- 'v*' - 'v*'
- 'e*'
branches: branches:
- 'master' - 'master'
- 'release-5[0-9]' - 'release-5[0-9]'
- 'ci/**' - 'ci/**'
workflow_dispatch:
inputs:
ref:
required: false
permissions: defaults:
contents: read run:
shell: bash
env: env:
IS_CI: 'yes' IS_CI: 'yes'
jobs: jobs:
init:
runs-on: ubuntu-22.04
outputs:
BUILDER_VSN: ${{ steps.env.outputs.BUILDER_VSN }}
OTP_VSN: ${{ steps.env.outputs.OTP_VSN }}
ELIXIR_VSN: ${{ steps.env.outputs.ELIXIR_VSN }}
BUILDER: ${{ steps.env.outputs.BUILDER }}
BUILD_FROM: ${{ steps.env.outputs.BUILD_FROM }}
RUN_FROM: ${{ steps.env.outputs.BUILD_FROM }}
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
ref: ${{ github.event.inputs.ref }}
- name: Set up environment
id: env
run: |
source env.sh
echo "BUILDER_VSN=$EMQX_BUILDER_VSN" >> "$GITHUB_OUTPUT"
echo "OTP_VSN=$OTP_VSN" >> "$GITHUB_OUTPUT"
echo "ELIXIR_VSN=$ELIXIR_VSN" >> "$GITHUB_OUTPUT"
echo "BUILDER=$EMQX_BUILDER" >> "$GITHUB_OUTPUT"
echo "BUILD_FROM=$EMQX_DOCKER_BUILD_FROM" >> "$GITHUB_OUTPUT"
echo "RUN_FROM=$EMQX_DOCKER_RUN_FROM" >> "$GITHUB_OUTPUT"
prepare: prepare:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
container: 'ghcr.io/emqx/emqx-builder/5.3-5:1.15.7-26.2.1-2-ubuntu22.04' needs: init
container: ${{ needs.init.outputs.BUILDER }}
outputs: outputs:
profile: ${{ steps.parse-git-ref.outputs.profile }} profile: ${{ steps.parse-git-ref.outputs.profile }}
release: ${{ steps.parse-git-ref.outputs.release }} release: ${{ steps.parse-git-ref.outputs.release }}
@ -31,13 +60,12 @@ jobs:
ct-matrix: ${{ steps.matrix.outputs.ct-matrix }} ct-matrix: ${{ steps.matrix.outputs.ct-matrix }}
ct-host: ${{ steps.matrix.outputs.ct-host }} ct-host: ${{ steps.matrix.outputs.ct-host }}
ct-docker: ${{ steps.matrix.outputs.ct-docker }} ct-docker: ${{ steps.matrix.outputs.ct-docker }}
builder: 'ghcr.io/emqx/emqx-builder/5.3-5:1.15.7-26.2.1-2-ubuntu22.04'
builder_vsn: '5.3-5' permissions:
otp_vsn: '26.2.1-2' contents: read
elixir_vsn: '1.15.7'
steps: steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
ref: ${{ github.event.inputs.ref }} ref: ${{ github.event.inputs.ref }}
fetch-depth: 0 fetch-depth: 0
@ -58,23 +86,9 @@ jobs:
- name: Build matrix - name: Build matrix
id: matrix id: matrix
run: | run: |
APPS="$(./scripts/find-apps.sh --ci)" MATRIX="$(./scripts/find-apps.sh --ci)"
MATRIX="$(echo "${APPS}" | jq -c '
[
(.[] | select(.profile == "emqx") | . + {
builder: "5.3-5",
otp: "26.2.1-2",
elixir: "1.15.7"
}),
(.[] | select(.profile == "emqx-enterprise") | . + {
builder: "5.3-5",
otp: ["26.2.1-2"][],
elixir: "1.15.7"
})
]
')"
echo "${MATRIX}" | jq echo "${MATRIX}" | jq
CT_MATRIX="$(echo "${MATRIX}" | jq -c 'map({profile, builder, otp, elixir}) | unique')" CT_MATRIX="$(echo "${MATRIX}" | jq -c 'map({profile}) | unique')"
CT_HOST="$(echo "${MATRIX}" | jq -c 'map(select(.runner == "host"))')" CT_HOST="$(echo "${MATRIX}" | jq -c 'map(select(.runner == "host"))')"
CT_DOCKER="$(echo "${MATRIX}" | jq -c 'map(select(.runner == "docker"))')" CT_DOCKER="$(echo "${MATRIX}" | jq -c 'map(select(.runner == "docker"))')"
echo "ct-matrix=${CT_MATRIX}" | tee -a $GITHUB_OUTPUT echo "ct-matrix=${CT_MATRIX}" | tee -a $GITHUB_OUTPUT
@ -84,47 +98,44 @@ jobs:
build_packages: build_packages:
if: needs.prepare.outputs.release == 'true' if: needs.prepare.outputs.release == 'true'
needs: needs:
- init
- prepare - prepare
uses: ./.github/workflows/build_packages.yaml uses: ./.github/workflows/build_packages.yaml
with: with:
profile: ${{ needs.prepare.outputs.profile }} profile: ${{ needs.prepare.outputs.profile }}
publish: true publish: true
otp_vsn: ${{ needs.prepare.outputs.otp_vsn }} otp_vsn: ${{ needs.init.outputs.OTP_VSN }}
elixir_vsn: ${{ needs.prepare.outputs.elixir_vsn }} elixir_vsn: ${{ needs.init.outputs.ELIXIR_VSN }}
builder_vsn: ${{ needs.prepare.outputs.builder_vsn }} builder_vsn: ${{ needs.init.outputs.BUILDER_VSN }}
secrets: inherit secrets: inherit
build_and_push_docker_images: build_and_push_docker_images:
if: needs.prepare.outputs.release == 'true' if: needs.prepare.outputs.release == 'true'
needs: needs:
- init
- prepare - prepare
uses: ./.github/workflows/build_and_push_docker_images.yaml uses: ./.github/workflows/build_and_push_docker_images.yaml
with: with:
profile: ${{ needs.prepare.outputs.profile }} profile: ${{ needs.prepare.outputs.profile }}
publish: true publish: true
latest: ${{ needs.prepare.outputs.latest }} latest: ${{ needs.prepare.outputs.latest }}
# TODO: revert this back to needs.prepare.outputs.otp_vsn when OTP 26 bug is fixed build_from: ${{ needs.init.outputs.BUILD_FROM }}
otp_vsn: 25.3.2-2 run_from: ${{ needs.init.outputs.RUN_FROM }}
elixir_vsn: ${{ needs.prepare.outputs.elixir_vsn }}
builder_vsn: ${{ needs.prepare.outputs.builder_vsn }}
secrets: inherit secrets: inherit
build_slim_packages: build_slim_packages:
if: needs.prepare.outputs.release != 'true' if: needs.prepare.outputs.release != 'true'
needs: needs:
- init
- prepare - prepare
uses: ./.github/workflows/build_slim_packages.yaml uses: ./.github/workflows/build_slim_packages.yaml
with:
builder: ${{ needs.prepare.outputs.builder }}
builder_vsn: ${{ needs.prepare.outputs.builder_vsn }}
otp_vsn: ${{ needs.prepare.outputs.otp_vsn }}
elixir_vsn: ${{ needs.prepare.outputs.elixir_vsn }}
compile: compile:
if: needs.prepare.outputs.release != 'true' if: needs.prepare.outputs.release != 'true'
runs-on: ${{ endsWith(github.repository, '/emqx') && 'ubuntu-22.04' || fromJSON('["self-hosted","ephemeral","linux","x64"]') }} runs-on: ${{ endsWith(github.repository, '/emqx') && 'ubuntu-22.04' || fromJSON('["self-hosted","ephemeral","linux","x64"]') }}
container: ${{ needs.prepare.outputs.builder }} container: ${{ needs.init.outputs.BUILDER }}
needs: needs:
- init
- prepare - prepare
strategy: strategy:
matrix: matrix:
@ -132,8 +143,11 @@ jobs:
- emqx - emqx
- emqx-enterprise - emqx-enterprise
permissions:
contents: read
steps: steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
ref: ${{ github.event.inputs.ref }} ref: ${{ github.event.inputs.ref }}
fetch-depth: 0 fetch-depth: 0
@ -149,7 +163,7 @@ jobs:
echo "PROFILE=${PROFILE}" | tee -a .env echo "PROFILE=${PROFILE}" | tee -a .env
echo "PKG_VSN=$(./pkg-vsn.sh ${PROFILE})" | tee -a .env echo "PKG_VSN=$(./pkg-vsn.sh ${PROFILE})" | tee -a .env
zip -ryq -x@.github/workflows/.zipignore $PROFILE.zip . zip -ryq -x@.github/workflows/.zipignore $PROFILE.zip .
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
with: with:
name: ${{ matrix.profile }} name: ${{ matrix.profile }}
path: ${{ matrix.profile }}.zip path: ${{ matrix.profile }}.zip
@ -157,22 +171,23 @@ jobs:
run_emqx_app_tests: run_emqx_app_tests:
needs: needs:
- prepare - init
- compile - compile
uses: ./.github/workflows/run_emqx_app_tests.yaml uses: ./.github/workflows/run_emqx_app_tests.yaml
with: with:
builder: ${{ needs.prepare.outputs.builder }} builder: ${{ needs.init.outputs.BUILDER }}
before_ref: ${{ github.event.before }} before_ref: ${{ github.event.before }}
after_ref: ${{ github.sha }} after_ref: ${{ github.sha }}
run_test_cases: run_test_cases:
if: needs.prepare.outputs.release != 'true' if: needs.prepare.outputs.release != 'true'
needs: needs:
- init
- prepare - prepare
- compile - compile
uses: ./.github/workflows/run_test_cases.yaml uses: ./.github/workflows/run_test_cases.yaml
with: with:
builder: ${{ needs.prepare.outputs.builder }} builder: ${{ needs.init.outputs.BUILDER }}
ct-matrix: ${{ needs.prepare.outputs.ct-matrix }} ct-matrix: ${{ needs.prepare.outputs.ct-matrix }}
ct-host: ${{ needs.prepare.outputs.ct-host }} ct-host: ${{ needs.prepare.outputs.ct-host }}
ct-docker: ${{ needs.prepare.outputs.ct-docker }} ct-docker: ${{ needs.prepare.outputs.ct-docker }}
@ -180,18 +195,20 @@ jobs:
run_conf_tests: run_conf_tests:
if: needs.prepare.outputs.release != 'true' if: needs.prepare.outputs.release != 'true'
needs: needs:
- init
- prepare - prepare
- compile - compile
uses: ./.github/workflows/run_conf_tests.yaml uses: ./.github/workflows/run_conf_tests.yaml
with: with:
builder: ${{ needs.prepare.outputs.builder }} builder: ${{ needs.init.outputs.BUILDER }}
static_checks: static_checks:
if: needs.prepare.outputs.release != 'true' if: needs.prepare.outputs.release != 'true'
needs: needs:
- init
- prepare - prepare
- compile - compile
uses: ./.github/workflows/static_checks.yaml uses: ./.github/workflows/static_checks.yaml
with: with:
builder: ${{ needs.prepare.outputs.builder }} builder: ${{ needs.init.outputs.BUILDER }}
ct-matrix: ${{ needs.prepare.outputs.ct-matrix }} ct-matrix: ${{ needs.prepare.outputs.ct-matrix }}

View File

@ -16,13 +16,10 @@ on:
publish: publish:
required: true required: true
type: boolean type: boolean
otp_vsn: build_from:
required: true required: true
type: string type: string
elixir_vsn: run_from:
required: true
type: string
builder_vsn:
required: true required: true
type: string type: string
secrets: secrets:
@ -50,18 +47,12 @@ on:
required: false required: false
type: boolean type: boolean
default: false default: false
otp_vsn: build_from:
required: false required: false
type: string type: string
default: '25.3.2-2' default: ghcr.io/emqx/emqx-builder/5.3-9:1.15.7-26.2.5-3-debian12
elixir_vsn: run_from:
required: false default: public.ecr.aws/debian/debian:stable-20240612-slim
type: string
default: '1.15.7'
builder_vsn:
required: false
type: string
default: '5.3-5'
permissions: permissions:
contents: read contents: read
@ -69,7 +60,7 @@ permissions:
jobs: jobs:
build: build:
runs-on: ${{ github.repository_owner == 'emqx' && fromJSON(format('["self-hosted","ephemeral","linux","{0}"]', matrix.arch)) || 'ubuntu-22.04' }} runs-on: ${{ github.repository_owner == 'emqx' && fromJSON(format('["self-hosted","ephemeral","linux","{0}"]', matrix.arch)) || 'ubuntu-22.04' }}
container: "ghcr.io/emqx/emqx-builder/${{ inputs.builder_vsn }}:${{ inputs.elixir_vsn }}-${{ inputs.otp_vsn }}-debian12" container: ${{ inputs.build_from }}
outputs: outputs:
PKG_VSN: ${{ steps.build.outputs.PKG_VSN }} PKG_VSN: ${{ steps.build.outputs.PKG_VSN }}
@ -84,7 +75,7 @@ jobs:
- arm64 - arm64
steps: steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
ref: ${{ github.event.inputs.ref }} ref: ${{ github.event.inputs.ref }}
- run: git config --global --add safe.directory "$PWD" - run: git config --global --add safe.directory "$PWD"
@ -92,7 +83,7 @@ jobs:
id: build id: build
run: | run: |
make ${{ matrix.profile }}-tgz make ${{ matrix.profile }}-tgz
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
with: with:
name: "${{ matrix.profile }}-${{ matrix.arch }}.tar.gz" name: "${{ matrix.profile }}-${{ matrix.arch }}.tar.gz"
path: "_packages/emqx*/emqx-*.tar.gz" path: "_packages/emqx*/emqx-*.tar.gz"
@ -116,10 +107,10 @@ jobs:
- ["${{ inputs.profile }}-elixir", "${{ inputs.profile == 'emqx' && 'docker.io,public.ecr.aws' || 'docker.io' }}"] - ["${{ inputs.profile }}-elixir", "${{ inputs.profile == 'emqx' && 'docker.io,public.ecr.aws' || 'docker.io' }}"]
steps: steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
ref: ${{ github.event.inputs.ref }} ref: ${{ github.event.inputs.ref }}
- uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with: with:
pattern: "${{ matrix.profile[0] }}-*.tar.gz" pattern: "${{ matrix.profile[0] }}-*.tar.gz"
path: _packages path: _packages
@ -131,32 +122,33 @@ jobs:
run: | run: |
ls -lR _packages/$PROFILE ls -lR _packages/$PROFILE
mv _packages/$PROFILE/*.tar.gz ./ mv _packages/$PROFILE/*.tar.gz ./
- name: Enable containerd image store on Docker Engine - name: Enable containerd image store on Docker Engine
run: | run: |
echo "$(jq '. += {"features": {"containerd-snapshotter": true}}' /etc/docker/daemon.json)" > daemon.json echo "$(sudo cat /etc/docker/daemon.json | jq '. += {"features": {"containerd-snapshotter": true}}')" > daemon.json
sudo mv daemon.json /etc/docker/daemon.json sudo mv daemon.json /etc/docker/daemon.json
sudo systemctl restart docker sudo systemctl restart docker
- uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0 - uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3.2.0
- uses: docker/setup-buildx-action@2b51285047da1547ffb1b2203d8be4c0af6b1f20 # v3.2.0 - uses: docker/setup-buildx-action@988b5a0280414f521da01fcc63a27aeeb4b104db # v3.6.1
- name: Login to hub.docker.com - name: Login to hub.docker.com
uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0 uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
if: inputs.publish || github.repository_owner != 'emqx' if: inputs.publish && contains(matrix.profile[1], 'docker.io')
with: with:
username: ${{ secrets.DOCKER_HUB_USER }} username: ${{ secrets.DOCKER_HUB_USER }}
password: ${{ secrets.DOCKER_HUB_TOKEN }} password: ${{ secrets.DOCKER_HUB_TOKEN }}
- name: Login to AWS ECR - name: Login to AWS ECR
uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0 uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
if: inputs.publish || github.repository_owner != 'emqx' if: inputs.publish && contains(matrix.profile[1], 'public.ecr.aws')
with: with:
registry: public.ecr.aws registry: public.ecr.aws
username: ${{ secrets.AWS_ACCESS_KEY_ID }} username: ${{ secrets.AWS_ACCESS_KEY_ID }}
password: ${{ secrets.AWS_SECRET_ACCESS_KEY }} password: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
ecr: true ecr: true
- name: Build docker image - name: Build docker image for smoke test
env: env:
PROFILE: ${{ matrix.profile[0] }} PROFILE: ${{ matrix.profile[0] }}
DOCKER_REGISTRY: ${{ matrix.profile[1] }} DOCKER_REGISTRY: ${{ matrix.profile[1] }}
@ -164,14 +156,9 @@ jobs:
DOCKER_LATEST: ${{ inputs.latest }} DOCKER_LATEST: ${{ inputs.latest }}
DOCKER_PUSH: false DOCKER_PUSH: false
DOCKER_BUILD_NOCACHE: true DOCKER_BUILD_NOCACHE: true
DOCKER_PLATFORMS: linux/amd64,linux/arm64 BUILD_FROM: ${{ inputs.build_from }}
DOCKER_LOAD: true RUN_FROM: ${{ inputs.run_from }}
EMQX_RUNNER: 'public.ecr.aws/debian/debian:12-slim'
EMQX_DOCKERFILE: 'deploy/docker/Dockerfile'
PKG_VSN: ${{ needs.build.outputs.PKG_VSN }} PKG_VSN: ${{ needs.build.outputs.PKG_VSN }}
EMQX_BUILDER_VERSION: ${{ inputs.builder_vsn }}
EMQX_BUILDER_OTP: ${{ inputs.otp_vsn }}
EMQX_BUILDER_ELIXIR: ${{ inputs.elixir_vsn }}
EMQX_SOURCE_TYPE: tgz EMQX_SOURCE_TYPE: tgz
run: | run: |
./build ${PROFILE} docker ./build ${PROFILE} docker
@ -185,7 +172,7 @@ jobs:
timeout-minutes: 1 timeout-minutes: 1
run: | run: |
for tag in $(cat .emqx_docker_image_tags); do for tag in $(cat .emqx_docker_image_tags); do
CID=$(docker run -d -P $tag) CID=$(docker run -d -p 18083:18083 $tag)
HTTP_PORT=$(docker inspect --format='{{(index (index .NetworkSettings.Ports "18083/tcp") 0).HostPort}}' $CID) HTTP_PORT=$(docker inspect --format='{{(index (index .NetworkSettings.Ports "18083/tcp") 0).HostPort}}' $CID)
./scripts/test/emqx-smoke-test.sh localhost $HTTP_PORT ./scripts/test/emqx-smoke-test.sh localhost $HTTP_PORT
docker rm -f $CID docker rm -f $CID
@ -203,7 +190,8 @@ jobs:
docker exec -t -u root -w /root $CID bash -c 'apt-get -y update && apt-get -y install net-tools' docker exec -t -u root -w /root $CID bash -c 'apt-get -y update && apt-get -y install net-tools'
docker exec -t -u root $CID node_dump docker exec -t -u root $CID node_dump
docker rm -f $CID docker rm -f $CID
- name: Push docker image
- name: Build and push docker image
if: inputs.publish || github.repository_owner != 'emqx' if: inputs.publish || github.repository_owner != 'emqx'
env: env:
PROFILE: ${{ matrix.profile[0] }} PROFILE: ${{ matrix.profile[0] }}
@ -214,12 +202,9 @@ jobs:
DOCKER_BUILD_NOCACHE: false DOCKER_BUILD_NOCACHE: false
DOCKER_PLATFORMS: linux/amd64,linux/arm64 DOCKER_PLATFORMS: linux/amd64,linux/arm64
DOCKER_LOAD: false DOCKER_LOAD: false
EMQX_RUNNER: 'public.ecr.aws/debian/debian:12-slim' BUILD_FROM: ${{ inputs.build_from }}
EMQX_DOCKERFILE: 'deploy/docker/Dockerfile' RUN_FROM: ${{ inputs.run_from }}
PKG_VSN: ${{ needs.build.outputs.PKG_VSN }} PKG_VSN: ${{ needs.build.outputs.PKG_VSN }}
EMQX_BUILDER_VERSION: ${{ inputs.builder_vsn }}
EMQX_BUILDER_OTP: ${{ inputs.otp_vsn }}
EMQX_BUILDER_ELIXIR: ${{ inputs.elixir_vsn }}
EMQX_SOURCE_TYPE: tgz EMQX_SOURCE_TYPE: tgz
run: | run: |
./build ${PROFILE} docker ./build ${PROFILE} docker

View File

@ -6,19 +6,6 @@ concurrency:
on: on:
workflow_call: workflow_call:
inputs:
otp_vsn:
required: true
type: string
elixir_vsn:
required: true
type: string
version-emqx:
required: true
type: string
version-emqx-enterprise:
required: true
type: string
permissions: permissions:
contents: read contents: read
@ -28,9 +15,6 @@ jobs:
runs-on: ${{ endsWith(github.repository, '/emqx') && 'ubuntu-22.04' || fromJSON('["self-hosted","ephemeral","linux","x64"]') }} runs-on: ${{ endsWith(github.repository, '/emqx') && 'ubuntu-22.04' || fromJSON('["self-hosted","ephemeral","linux","x64"]') }}
env: env:
EMQX_NAME: ${{ matrix.profile }} EMQX_NAME: ${{ matrix.profile }}
PKG_VSN: ${{ matrix.profile == 'emqx-enterprise' && inputs.version-emqx-enterprise || inputs.version-emqx }}
OTP_VSN: ${{ inputs.otp_vsn }}
ELIXIR_VSN: ${{ inputs.elixir_vsn }}
strategy: strategy:
fail-fast: false fail-fast: false
@ -42,7 +26,13 @@ jobs:
- emqx-enterprise-elixir - emqx-enterprise-elixir
steps: steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Set up environment
id: env
run: |
source env.sh
PKG_VSN=$(docker run --rm -v $(pwd):$(pwd) -w $(pwd) -u $(id -u) "$EMQX_BUILDER" ./pkg-vsn.sh "$EMQX_NAME")
echo "PKG_VSN=$PKG_VSN" >> "$GITHUB_ENV"
- name: build and export to Docker - name: build and export to Docker
id: build id: build
run: | run: |
@ -52,12 +42,16 @@ jobs:
run: | run: |
CID=$(docker run -d --rm -P $_EMQX_DOCKER_IMAGE_TAG) CID=$(docker run -d --rm -P $_EMQX_DOCKER_IMAGE_TAG)
HTTP_PORT=$(docker inspect --format='{{(index (index .NetworkSettings.Ports "18083/tcp") 0).HostPort}}' $CID) HTTP_PORT=$(docker inspect --format='{{(index (index .NetworkSettings.Ports "18083/tcp") 0).HostPort}}' $CID)
./scripts/test/emqx-smoke-test.sh localhost $HTTP_PORT ./scripts/test/emqx-smoke-test.sh localhost $HTTP_PORT || {
docker logs $CID
exit 1
}
docker stop $CID docker stop $CID
- name: export docker image - name: export docker image
if: always()
run: | run: |
docker save $_EMQX_DOCKER_IMAGE_TAG | gzip > $EMQX_NAME-docker-$PKG_VSN.tar.gz docker save $_EMQX_DOCKER_IMAGE_TAG | gzip > $EMQX_NAME-docker-$PKG_VSN.tar.gz
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
with: with:
name: "${{ env.EMQX_NAME }}-docker" name: "${{ env.EMQX_NAME }}-docker"
path: "${{ env.EMQX_NAME }}-docker-${{ env.PKG_VSN }}.tar.gz" path: "${{ env.EMQX_NAME }}-docker-${{ env.PKG_VSN }}.tar.gz"

View File

@ -55,7 +55,7 @@ on:
otp_vsn: otp_vsn:
required: false required: false
type: string type: string
default: '26.2.1-2' default: '26.2.5-3'
elixir_vsn: elixir_vsn:
required: false required: false
type: string type: string
@ -63,7 +63,7 @@ on:
builder_vsn: builder_vsn:
required: false required: false
type: string type: string
default: '5.3-5' default: '5.3-9'
permissions: permissions:
contents: read contents: read
@ -82,7 +82,7 @@ jobs:
- ${{ inputs.otp_vsn }} - ${{ inputs.otp_vsn }}
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
ref: ${{ github.event.inputs.ref }} ref: ${{ github.event.inputs.ref }}
fetch-depth: 0 fetch-depth: 0
@ -95,7 +95,7 @@ jobs:
apple_developer_identity: ${{ secrets.APPLE_DEVELOPER_IDENTITY }} apple_developer_identity: ${{ secrets.APPLE_DEVELOPER_IDENTITY }}
apple_developer_id_bundle: ${{ secrets.APPLE_DEVELOPER_ID_BUNDLE }} apple_developer_id_bundle: ${{ secrets.APPLE_DEVELOPER_ID_BUNDLE }}
apple_developer_id_bundle_password: ${{ secrets.APPLE_DEVELOPER_ID_BUNDLE_PASSWORD }} apple_developer_id_bundle_password: ${{ secrets.APPLE_DEVELOPER_ID_BUNDLE_PASSWORD }}
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
if: success() if: success()
with: with:
name: ${{ matrix.profile }}-${{ matrix.os }}-${{ matrix.otp }} name: ${{ matrix.profile }}-${{ matrix.os }}-${{ matrix.otp }}
@ -113,13 +113,11 @@ jobs:
- ubuntu24.04 - ubuntu24.04
- ubuntu22.04 - ubuntu22.04
- ubuntu20.04 - ubuntu20.04
- ubuntu18.04
- debian12 - debian12
- debian11 - debian11
- debian10 - debian10
- el9 - el9
- el8 - el8
- el7
- amzn2 - amzn2
- amzn2023 - amzn2023
arch: arch:
@ -147,7 +145,7 @@ jobs:
shell: bash shell: bash
steps: steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
ref: ${{ github.event.inputs.ref }} ref: ${{ github.event.inputs.ref }}
fetch-depth: 0 fetch-depth: 0
@ -182,7 +180,7 @@ jobs:
--builder $BUILDER \ --builder $BUILDER \
--elixir $IS_ELIXIR \ --elixir $IS_ELIXIR \
--pkgtype pkg --pkgtype pkg
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
with: with:
name: ${{ matrix.profile }}-${{ matrix.os }}-${{ matrix.arch }}${{ matrix.with_elixir == 'yes' && '-elixir' || '' }}-${{ matrix.builder }}-${{ matrix.otp }}-${{ matrix.elixir }} name: ${{ matrix.profile }}-${{ matrix.os }}-${{ matrix.arch }}${{ matrix.with_elixir == 'yes' && '-elixir' || '' }}-${{ matrix.builder }}-${{ matrix.otp }}-${{ matrix.elixir }}
path: _packages/${{ matrix.profile }}/ path: _packages/${{ matrix.profile }}/
@ -200,23 +198,11 @@ jobs:
profile: profile:
- ${{ inputs.profile }} - ${{ inputs.profile }}
steps: steps:
- uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with: with:
pattern: "${{ matrix.profile }}-*" pattern: "${{ matrix.profile }}-*"
path: packages/${{ matrix.profile }} path: packages/${{ matrix.profile }}
merge-multiple: true merge-multiple: true
- name: install dos2unix
run: sudo apt-get update -y && sudo apt install -y dos2unix
- name: get packages
run: |
set -eu
cd packages/${{ matrix.profile }}
# fix the .sha256 file format
for f in *.sha256; do
dos2unix $f
echo "$(cat $f) ${f%.*}" | sha256sum -c || exit 1
done
cd -
- uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 - uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
with: with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}

View File

@ -16,63 +16,52 @@ jobs:
linux: linux:
if: github.repository_owner == 'emqx' if: github.repository_owner == 'emqx'
runs-on: ${{ endsWith(github.repository, '/emqx') && 'ubuntu-22.04' || fromJSON('["self-hosted","ephemeral","linux","x64"]') }} runs-on: ${{ endsWith(github.repository, '/emqx') && 'ubuntu-22.04' || fromJSON('["self-hosted","ephemeral","linux","x64"]') }}
container:
image: "ghcr.io/emqx/emqx-builder/${{ matrix.profile[2] }}-${{ matrix.os }}"
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
profile: profile:
- ['emqx', 'master', '5.3-5:1.15.7-26.2.1-2'] - ['emqx', 'master']
- ['emqx', 'release-57', '5.3-5:1.15.7-26.2.1-2'] - ['emqx', 'release-57']
- ['emqx', 'release-58']
os: os:
- ubuntu22.04 - ubuntu22.04
- amzn2023 - amzn2023
env:
PROFILE: ${{ matrix.profile[0] }}
OS: ${{ matrix.os }}
BUILDER_SYSTEM: force_docker
defaults: defaults:
run: run:
shell: bash shell: bash
steps: steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
ref: ${{ matrix.profile[1] }} ref: ${{ matrix.profile[1] }}
fetch-depth: 0 fetch-depth: 0
- name: Set up environment
- name: fix workdir id: env
run: | run: |
set -eu source env.sh
git config --global --add safe.directory "$GITHUB_WORKSPACE" BUILDER="ghcr.io/emqx/emqx-builder/${EMQX_BUILDER_VSN}:${ELIXIR_VSN}-${OTP_VSN}-${OS}"
# Align path for CMake caches echo "BUILDER=$BUILDER" >> "$GITHUB_ENV"
if [ ! "$PWD" = "/emqx" ]; then - name: build tgz
ln -s $PWD /emqx
cd /emqx
fi
echo "pwd is $PWD"
- name: build emqx packages
env:
PROFILE: ${{ matrix.profile[0] }}
ACLOCAL_PATH: "/usr/share/aclocal:/usr/local/share/aclocal"
run: | run: |
set -eu ./scripts/buildx.sh --profile "$PROFILE" --pkgtype tgz --builder "$BUILDER"
make "${PROFILE}-tgz" - name: build pkg
make "${PROFILE}-pkg"
- name: test emqx packages
env:
PROFILE: ${{ matrix.profile[0] }}
run: | run: |
set -eu ./scripts/buildx.sh --profile "$PROFILE" --pkgtype pkg --builder "$BUILDER"
./scripts/pkg-tests.sh "${PROFILE}-tgz" - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
./scripts/pkg-tests.sh "${PROFILE}-pkg"
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
if: success() if: success()
with: with:
name: ${{ matrix.profile[0] }}-${{ matrix.os }} name: ${{ matrix.profile[0] }}-${{ matrix.profile[1] }}-${{ matrix.os }}
path: _packages/${{ matrix.profile[0] }}/ path: _packages/${{ matrix.profile[0] }}/
retention-days: 7 retention-days: 7
- name: Send notification to Slack - name: Send notification to Slack
uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0
if: failure() if: failure()
env: env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
@ -91,33 +80,36 @@ jobs:
- emqx - emqx
branch: branch:
- master - master
otp:
- 26.2.1-2
os: os:
- macos-12-arm64 - macos-14-arm64
steps: steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
ref: ${{ matrix.branch }} ref: ${{ matrix.branch }}
fetch-depth: 0 fetch-depth: 0
- name: Set up environment
id: env
run: |
source env.sh
echo "OTP_VSN=$OTP_VSN" >> "$GITHUB_OUTPUT"
- uses: ./.github/actions/package-macos - uses: ./.github/actions/package-macos
with: with:
profile: ${{ matrix.profile }} profile: ${{ matrix.profile }}
otp: ${{ matrix.otp }} otp: ${{ steps.env.outputs.OTP_VSN }}
os: ${{ matrix.os }} os: ${{ matrix.os }}
apple_id_password: ${{ secrets.APPLE_ID_PASSWORD }} apple_id_password: ${{ secrets.APPLE_ID_PASSWORD }}
apple_developer_identity: ${{ secrets.APPLE_DEVELOPER_IDENTITY }} apple_developer_identity: ${{ secrets.APPLE_DEVELOPER_IDENTITY }}
apple_developer_id_bundle: ${{ secrets.APPLE_DEVELOPER_ID_BUNDLE }} apple_developer_id_bundle: ${{ secrets.APPLE_DEVELOPER_ID_BUNDLE }}
apple_developer_id_bundle_password: ${{ secrets.APPLE_DEVELOPER_ID_BUNDLE_PASSWORD }} apple_developer_id_bundle_password: ${{ secrets.APPLE_DEVELOPER_ID_BUNDLE_PASSWORD }}
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
if: success() if: success()
with: with:
name: ${{ matrix.profile }}-${{ matrix.os }} name: ${{ matrix.profile }}-${{ matrix.os }}
path: _packages/${{ matrix.profile }}/ path: _packages/${{ matrix.profile }}/
retention-days: 7 retention-days: 7
- name: Send notification to Slack - name: Send notification to Slack
uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0
if: failure() if: failure()
env: env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}

View File

@ -6,97 +6,50 @@ concurrency:
on: on:
workflow_call: workflow_call:
inputs:
builder:
required: true
type: string
builder_vsn:
required: true
type: string
otp_vsn:
required: true
type: string
elixir_vsn:
required: true
type: string
workflow_dispatch: workflow_dispatch:
inputs: inputs:
ref: ref:
required: false required: false
builder:
required: false
type: string
default: 'ghcr.io/emqx/emqx-builder/5.3-5:1.15.7-26.2.1-2-ubuntu22.04'
builder_vsn:
required: false
type: string
default: '5.3-5'
otp_vsn:
required: false
type: string
default: '26.2.1-2'
elixir_vsn:
required: false
type: string
default: '1.15.7'
permissions: permissions:
contents: read contents: read
jobs: jobs:
linux: linux:
runs-on: ${{ github.repository_owner == 'emqx' && fromJSON(format('["self-hosted","ephemeral","linux","{0}"]', matrix.profile[4])) || 'ubuntu-22.04' }} runs-on: ${{ github.repository_owner == 'emqx' && fromJSON(format('["self-hosted","ephemeral","linux","{0}"]', matrix.profile[2])) || 'ubuntu-22.04' }}
env: env:
EMQX_NAME: ${{ matrix.profile[0] }} PROFILE: ${{ matrix.profile[0] }}
ELIXIR: ${{ matrix.profile[1] == 'elixir' && 'yes' || 'no' }}
ARCH: ${{ matrix.profile[2] == 'x64' && 'amd64' || 'arm64' }}
BUILDER_SYSTEM: force_docker
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
profile: profile:
- ["emqx", "26.2.1-2", "ubuntu22.04", "elixir", "x64"] - ["emqx", "elixir", "x64"]
- ["emqx", "26.2.1-2", "ubuntu22.04", "elixir", "arm64"] - ["emqx", "elixir", "arm64"]
- ["emqx-enterprise", "26.2.1-2", "ubuntu22.04", "erlang", "x64"] - ["emqx-enterprise", "erlang", "x64"]
container: "ghcr.io/emqx/emqx-builder/${{ inputs.builder_vsn }}:${{ inputs.elixir_vsn }}-${{ matrix.profile[1] }}-${{ matrix.profile[2] }}"
steps: steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Work around https://github.com/actions/checkout/issues/766 - name: build tgz
run: | run: |
git config --global --add safe.directory "$GITHUB_WORKSPACE" ./scripts/buildx.sh --profile $PROFILE --pkgtype tgz --elixir $ELIXIR --arch $ARCH
echo "CODE_PATH=$GITHUB_WORKSPACE" >> $GITHUB_ENV - name: build pkg
- name: build and test tgz package
if: matrix.profile[3] == 'erlang'
run: | run: |
make ${EMQX_NAME}-tgz ./scripts/buildx.sh --profile $PROFILE --pkgtype pkg --elixir $ELIXIR --arch $ARCH
./scripts/pkg-tests.sh ${EMQX_NAME}-tgz - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
- name: build and test deb/rpm packages
if: matrix.profile[3] == 'erlang'
run: |
make ${EMQX_NAME}-pkg
./scripts/pkg-tests.sh ${EMQX_NAME}-pkg
- name: build and test tgz package (Elixir)
if: matrix.profile[3] == 'elixir'
run: |
make ${EMQX_NAME}-elixir-tgz
./scripts/pkg-tests.sh ${EMQX_NAME}-elixir-tgz
- name: build and test deb/rpm packages (Elixir)
if: matrix.profile[3] == 'elixir'
run: |
make ${EMQX_NAME}-elixir-pkg
./scripts/pkg-tests.sh ${EMQX_NAME}-elixir-pkg
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: "${{ matrix.profile[0] }}-${{ matrix.profile[1] }}-${{ matrix.profile[2] }}-${{ matrix.profile[3] }}-${{ matrix.profile[4] }}" name: "${{ matrix.profile[0] }}-${{ matrix.profile[1] }}-${{ matrix.profile[2] }}"
path: _packages/${{ matrix.profile[0] }}/* path: _packages/${{ matrix.profile[0] }}/*
retention-days: 7 retention-days: 7
compression-level: 0 compression-level: 0
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
with: with:
name: "${{ matrix.profile[0] }}-schema-dump-${{ matrix.profile[1] }}-${{ matrix.profile[2] }}-${{ matrix.profile[3] }}-${{ matrix.profile[4] }}" name: "${{ matrix.profile[0] }}-schema-dump-${{ matrix.profile[1] }}-${{ matrix.profile[2] }}"
path: | path: |
scripts/spellcheck scripts/spellcheck
_build/docgen/${{ matrix.profile[0] }}/schema-en.json _build/docgen/${{ matrix.profile[0] }}/schema-en.json
@ -108,27 +61,30 @@ jobs:
matrix: matrix:
profile: profile:
- emqx - emqx
otp:
- ${{ inputs.otp_vsn }}
os: os:
- macos-14 - macos-14-arm64
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
env: env:
EMQX_NAME: ${{ matrix.profile }} EMQX_NAME: ${{ matrix.profile }}
steps: steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Set up environment
id: env
run: |
source env.sh
echo "OTP_VSN=$OTP_VSN" >> "$GITHUB_OUTPUT"
- uses: ./.github/actions/package-macos - uses: ./.github/actions/package-macos
with: with:
profile: ${{ matrix.profile }} profile: ${{ matrix.profile }}
otp: ${{ matrix.otp }} otp: ${{ steps.env.outputs.OTP_VSN }}
os: ${{ matrix.os }} os: ${{ matrix.os }}
apple_id_password: ${{ secrets.APPLE_ID_PASSWORD }} apple_id_password: ${{ secrets.APPLE_ID_PASSWORD }}
apple_developer_identity: ${{ secrets.APPLE_DEVELOPER_IDENTITY }} apple_developer_identity: ${{ secrets.APPLE_DEVELOPER_IDENTITY }}
apple_developer_id_bundle: ${{ secrets.APPLE_DEVELOPER_ID_BUNDLE }} apple_developer_id_bundle: ${{ secrets.APPLE_DEVELOPER_ID_BUNDLE }}
apple_developer_id_bundle_password: ${{ secrets.APPLE_DEVELOPER_ID_BUNDLE_PASSWORD }} apple_developer_id_bundle_password: ${{ secrets.APPLE_DEVELOPER_ID_BUNDLE_PASSWORD }}
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
with: with:
name: ${{ matrix.os }} name: ${{ matrix.os }}
path: _packages/**/* path: _packages/**/*

View File

@ -22,13 +22,14 @@ jobs:
profile: profile:
- emqx-enterprise - emqx-enterprise
steps: steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- run: git config --global --add safe.directory "$GITHUB_WORKSPACE" - run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
- run: make ensure-rebar3 - run: make ensure-rebar3
- run: ./scripts/check-deps-integrity.escript - run: ./scripts/check-deps-integrity.escript
- name: Setup mix - name: Setup mix
run: | run: |
mix local.hex --force # mix local.hex --force
mix local.hex 2.0.6 --force
mix local.rebar --force mix local.rebar --force
mix deps.get mix deps.get
- name: print mix dependency tree - name: print mix dependency tree
@ -36,7 +37,7 @@ jobs:
- run: ./scripts/check-elixir-deps-discrepancies.exs - run: ./scripts/check-elixir-deps-discrepancies.exs
- run: ./scripts/check-elixir-applications.exs - run: ./scripts/check-elixir-applications.exs
- name: Upload produced lock files - name: Upload produced lock files
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
if: failure() if: failure()
with: with:
name: ${{ matrix.profile }}_produced_lock_files name: ${{ matrix.profile }}_produced_lock_files

View File

@ -10,14 +10,13 @@ permissions:
jobs: jobs:
analyze: analyze:
if: github.repository == 'emqx/emqx'
name: Analyze name: Analyze
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
timeout-minutes: 360 timeout-minutes: 360
permissions: permissions:
actions: read actions: read
security-events: write security-events: write
container:
image: ghcr.io/emqx/emqx-builder/5.3-5:1.15.7-26.2.1-2-ubuntu22.04
strategy: strategy:
fail-fast: false fail-fast: false
@ -25,21 +24,17 @@ jobs:
branch: branch:
- master - master
- release-57 - release-57
- release-58
language: language:
- cpp - cpp
- python - python
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
ref: ${{ matrix.branch }} ref: ${{ matrix.branch }}
- name: Ensure git safe dir
run: |
git config --global --add safe.directory "$GITHUB_WORKSPACE"
make ensure-rebar3
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@7e187e1c529d80bac7b87a16e7a792427f65cf02 # v2.15.5 uses: github/codeql-action/init@7e187e1c529d80bac7b87a16e7a792427f65cf02 # v2.15.5
with: with:
@ -50,14 +45,7 @@ jobs:
env: env:
PROFILE: emqx-enterprise PROFILE: emqx-enterprise
run: | run: |
make emqx-enterprise-compile ./scripts/buildx.sh --profile emqx-enterprise --pkgtype rel
- name: Fetch deps
if: matrix.language == 'python'
env:
PROFILE: emqx-enterprise
run: |
make deps-emqx-enterprise
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@7e187e1c529d80bac7b87a16e7a792427f65cf02 # v2.15.5 uses: github/codeql-action/analyze@7e187e1c529d80bac7b87a16e7a792427f65cf02 # v2.15.5

View File

@ -7,9 +7,6 @@ on:
# run hourly # run hourly
- cron: "0 * * * *" - cron: "0 * * * *"
workflow_dispatch: workflow_dispatch:
inputs:
ref:
required: false
permissions: permissions:
contents: read contents: read
@ -17,22 +14,30 @@ permissions:
jobs: jobs:
rerun-failed-jobs: rerun-failed-jobs:
if: github.repository_owner == 'emqx' if: github.repository_owner == 'emqx'
runs-on: ubuntu-22.04 runs-on: ubuntu-latest
permissions: permissions:
checks: read checks: read
actions: write actions: write
strategy:
fail-fast: false
matrix:
ref:
- master
- release-57
- release-58
steps: steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
ref: ${{ github.event.inputs.ref || 'master' }} ref: ${{ matrix.ref }}
- name: run script - name: run script
shell: bash shell: bash
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_REPO: ${{ github.repository }}
run: | run: |
gh api --method GET -f head_sha=$(git rev-parse HEAD) -f status=completed -f exclude_pull_requests=true /repos/emqx/emqx/actions/runs > runs.json gh api --method GET -f head_sha=$(git rev-parse HEAD) -f status=completed -f exclude_pull_requests=true /repos/${GITHUB_REPO}/actions/runs > runs.json
for id in $(jq -r '.workflow_runs[] | select((."conclusion" == "failure") and (."name" != "Keep master green") and .run_attempt < 3) | .id' runs.json); do for id in $(jq -r '.workflow_runs[] | select((."conclusion" == "failure") and (."name" != "Keep master green") and .run_attempt < 3) | .id' runs.json); do
echo "rerun https://github.com/emqx/emqx/actions/runs/$id" echo "rerun https://github.com/${GITHUB_REPO}/actions/runs/$id"
gh api --method POST /repos/emqx/emqx/actions/runs/$id/rerun-failed-jobs || true gh api --method POST /repos/${GITHUB_REPO}/actions/runs/$id/rerun-failed-jobs || true
done done

View File

@ -26,13 +26,13 @@ jobs:
prepare: prepare:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.repository_owner == 'emqx' if: github.repository_owner == 'emqx'
container: ghcr.io/emqx/emqx-builder/5.3-5:1.15.7-26.2.1-2-ubuntu20.04 container: ghcr.io/emqx/emqx-builder/5.3-9:1.15.7-26.2.5-3-ubuntu20.04
outputs: outputs:
BENCH_ID: ${{ steps.prepare.outputs.BENCH_ID }} BENCH_ID: ${{ steps.prepare.outputs.BENCH_ID }}
PACKAGE_FILE: ${{ steps.package_file.outputs.PACKAGE_FILE }} PACKAGE_FILE: ${{ steps.package_file.outputs.PACKAGE_FILE }}
steps: steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
fetch-depth: 0 fetch-depth: 0
ref: ${{ github.event.inputs.ref }} ref: ${{ github.event.inputs.ref }}
@ -52,7 +52,7 @@ jobs:
id: package_file id: package_file
run: | run: |
echo "PACKAGE_FILE=$(find _packages/emqx -name 'emqx-*.deb' | head -n 1 | xargs basename)" >> $GITHUB_OUTPUT echo "PACKAGE_FILE=$(find _packages/emqx -name 'emqx-*.deb' | head -n 1 | xargs basename)" >> $GITHUB_OUTPUT
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
with: with:
name: emqx-ubuntu20.04 name: emqx-ubuntu20.04
path: _packages/emqx/${{ steps.package_file.outputs.PACKAGE_FILE }} path: _packages/emqx/${{ steps.package_file.outputs.PACKAGE_FILE }}
@ -72,17 +72,17 @@ jobs:
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY_PERF_TEST }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY_PERF_TEST }}
aws-region: eu-west-1 aws-region: eu-west-1
- name: Checkout tf-emqx-performance-test - name: Checkout tf-emqx-performance-test
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
repository: emqx/tf-emqx-performance-test repository: emqx/tf-emqx-performance-test
path: tf-emqx-performance-test path: tf-emqx-performance-test
ref: v0.2.3 ref: v0.2.3
- uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with: with:
name: emqx-ubuntu20.04 name: emqx-ubuntu20.04
path: tf-emqx-performance-test/ path: tf-emqx-performance-test/
- name: Setup Terraform - name: Setup Terraform
uses: hashicorp/setup-terraform@a1502cd9e758c50496cc9ac5308c4843bcd56d36 # v3.0.0 uses: hashicorp/setup-terraform@651471c36a6092792c552e8b1bef71e592b462d8 # v3.1.1
with: with:
terraform_wrapper: false terraform_wrapper: false
- name: run scenario - name: run scenario
@ -105,7 +105,7 @@ jobs:
terraform destroy -auto-approve terraform destroy -auto-approve
aws s3 sync --exclude '*' --include '*.tar.gz' s3://$TF_VAR_s3_bucket_name/$TF_VAR_bench_id . aws s3 sync --exclude '*' --include '*.tar.gz' s3://$TF_VAR_s3_bucket_name/$TF_VAR_bench_id .
- name: Send notification to Slack - name: Send notification to Slack
uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0
with: with:
payload-file-path: "./tf-emqx-performance-test/slack-payload.json" payload-file-path: "./tf-emqx-performance-test/slack-payload.json"
- name: terraform destroy - name: terraform destroy
@ -113,13 +113,13 @@ jobs:
working-directory: ./tf-emqx-performance-test working-directory: ./tf-emqx-performance-test
run: | run: |
terraform destroy -auto-approve terraform destroy -auto-approve
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
if: success() if: success()
with: with:
name: metrics name: metrics
path: | path: |
"./tf-emqx-performance-test/*.tar.gz" "./tf-emqx-performance-test/*.tar.gz"
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
if: failure() if: failure()
with: with:
name: terraform name: terraform
@ -143,17 +143,17 @@ jobs:
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY_PERF_TEST }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY_PERF_TEST }}
aws-region: eu-west-1 aws-region: eu-west-1
- name: Checkout tf-emqx-performance-test - name: Checkout tf-emqx-performance-test
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
repository: emqx/tf-emqx-performance-test repository: emqx/tf-emqx-performance-test
path: tf-emqx-performance-test path: tf-emqx-performance-test
ref: v0.2.3 ref: v0.2.3
- uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with: with:
name: emqx-ubuntu20.04 name: emqx-ubuntu20.04
path: tf-emqx-performance-test/ path: tf-emqx-performance-test/
- name: Setup Terraform - name: Setup Terraform
uses: hashicorp/setup-terraform@a1502cd9e758c50496cc9ac5308c4843bcd56d36 # v3.0.0 uses: hashicorp/setup-terraform@651471c36a6092792c552e8b1bef71e592b462d8 # v3.1.1
with: with:
terraform_wrapper: false terraform_wrapper: false
- name: run scenario - name: run scenario
@ -176,7 +176,7 @@ jobs:
terraform destroy -auto-approve terraform destroy -auto-approve
aws s3 sync --exclude '*' --include '*.tar.gz' s3://$TF_VAR_s3_bucket_name/$TF_VAR_bench_id . aws s3 sync --exclude '*' --include '*.tar.gz' s3://$TF_VAR_s3_bucket_name/$TF_VAR_bench_id .
- name: Send notification to Slack - name: Send notification to Slack
uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0
with: with:
payload-file-path: "./tf-emqx-performance-test/slack-payload.json" payload-file-path: "./tf-emqx-performance-test/slack-payload.json"
- name: terraform destroy - name: terraform destroy
@ -184,13 +184,13 @@ jobs:
working-directory: ./tf-emqx-performance-test working-directory: ./tf-emqx-performance-test
run: | run: |
terraform destroy -auto-approve terraform destroy -auto-approve
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
if: success() if: success()
with: with:
name: metrics name: metrics
path: | path: |
"./tf-emqx-performance-test/*.tar.gz" "./tf-emqx-performance-test/*.tar.gz"
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
if: failure() if: failure()
with: with:
name: terraform name: terraform
@ -215,17 +215,17 @@ jobs:
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY_PERF_TEST }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY_PERF_TEST }}
aws-region: eu-west-1 aws-region: eu-west-1
- name: Checkout tf-emqx-performance-test - name: Checkout tf-emqx-performance-test
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
repository: emqx/tf-emqx-performance-test repository: emqx/tf-emqx-performance-test
path: tf-emqx-performance-test path: tf-emqx-performance-test
ref: v0.2.3 ref: v0.2.3
- uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with: with:
name: emqx-ubuntu20.04 name: emqx-ubuntu20.04
path: tf-emqx-performance-test/ path: tf-emqx-performance-test/
- name: Setup Terraform - name: Setup Terraform
uses: hashicorp/setup-terraform@a1502cd9e758c50496cc9ac5308c4843bcd56d36 # v3.0.0 uses: hashicorp/setup-terraform@651471c36a6092792c552e8b1bef71e592b462d8 # v3.1.1
with: with:
terraform_wrapper: false terraform_wrapper: false
- name: run scenario - name: run scenario
@ -249,7 +249,7 @@ jobs:
terraform destroy -auto-approve terraform destroy -auto-approve
aws s3 sync --exclude '*' --include '*.tar.gz' s3://$TF_VAR_s3_bucket_name/$TF_VAR_bench_id . aws s3 sync --exclude '*' --include '*.tar.gz' s3://$TF_VAR_s3_bucket_name/$TF_VAR_bench_id .
- name: Send notification to Slack - name: Send notification to Slack
uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0
with: with:
payload-file-path: "./tf-emqx-performance-test/slack-payload.json" payload-file-path: "./tf-emqx-performance-test/slack-payload.json"
- name: terraform destroy - name: terraform destroy
@ -257,13 +257,13 @@ jobs:
working-directory: ./tf-emqx-performance-test working-directory: ./tf-emqx-performance-test
run: | run: |
terraform destroy -auto-approve terraform destroy -auto-approve
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
if: success() if: success()
with: with:
name: metrics name: metrics
path: | path: |
"./tf-emqx-performance-test/*.tar.gz" "./tf-emqx-performance-test/*.tar.gz"
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
if: failure() if: failure()
with: with:
name: terraform name: terraform
@ -289,17 +289,17 @@ jobs:
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY_PERF_TEST }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY_PERF_TEST }}
aws-region: eu-west-1 aws-region: eu-west-1
- name: Checkout tf-emqx-performance-test - name: Checkout tf-emqx-performance-test
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
repository: emqx/tf-emqx-performance-test repository: emqx/tf-emqx-performance-test
path: tf-emqx-performance-test path: tf-emqx-performance-test
ref: v0.2.3 ref: v0.2.3
- uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with: with:
name: emqx-ubuntu20.04 name: emqx-ubuntu20.04
path: tf-emqx-performance-test/ path: tf-emqx-performance-test/
- name: Setup Terraform - name: Setup Terraform
uses: hashicorp/setup-terraform@a1502cd9e758c50496cc9ac5308c4843bcd56d36 # v3.0.0 uses: hashicorp/setup-terraform@651471c36a6092792c552e8b1bef71e592b462d8 # v3.1.1
with: with:
terraform_wrapper: false terraform_wrapper: false
- name: run scenario - name: run scenario
@ -322,7 +322,7 @@ jobs:
terraform destroy -auto-approve terraform destroy -auto-approve
aws s3 sync --exclude '*' --include '*.tar.gz' s3://$TF_VAR_s3_bucket_name/$TF_VAR_bench_id . aws s3 sync --exclude '*' --include '*.tar.gz' s3://$TF_VAR_s3_bucket_name/$TF_VAR_bench_id .
- name: Send notification to Slack - name: Send notification to Slack
uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0
with: with:
payload-file-path: "./tf-emqx-performance-test/slack-payload.json" payload-file-path: "./tf-emqx-performance-test/slack-payload.json"
- name: terraform destroy - name: terraform destroy
@ -330,13 +330,13 @@ jobs:
working-directory: ./tf-emqx-performance-test working-directory: ./tf-emqx-performance-test
run: | run: |
terraform destroy -auto-approve terraform destroy -auto-approve
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
if: success() if: success()
with: with:
name: metrics name: metrics
path: | path: |
"./tf-emqx-performance-test/*.tar.gz" "./tf-emqx-performance-test/*.tar.gz"
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
if: failure() if: failure()
with: with:
name: terraform name: terraform

View File

@ -8,7 +8,7 @@ on:
tag: tag:
type: string type: string
required: true required: true
publish_release_artefacts: publish_release_artifacts:
type: boolean type: boolean
required: true required: true
default: false default: false
@ -36,7 +36,7 @@ jobs:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_DEFAULT_REGION }} aws-region: ${{ secrets.AWS_DEFAULT_REGION }}
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
ref: ${{ github.event.inputs.tag }} ref: ${{ github.event.inputs.tag }}
- name: Detect profile - name: Detect profile
@ -75,7 +75,7 @@ jobs:
tag_name: "${{ env.ref_name }}" tag_name: "${{ env.ref_name }}"
skip_existing: true skip_existing: true
- name: update to emqx.io - name: update to emqx.io
if: startsWith(env.ref_name, 'v') && ((github.event_name == 'release' && !github.event.release.prerelease) || inputs.publish_release_artefacts) if: github.event_name == 'release' || inputs.publish_release_artifacts
run: | run: |
set -eux set -eux
curl -w %{http_code} \ curl -w %{http_code} \
@ -86,7 +86,7 @@ jobs:
-d "{\"repo\":\"emqx/emqx\", \"tag\": \"${{ env.ref_name }}\" }" \ -d "{\"repo\":\"emqx/emqx\", \"tag\": \"${{ env.ref_name }}\" }" \
${{ secrets.EMQX_IO_RELEASE_API }} ${{ secrets.EMQX_IO_RELEASE_API }}
- name: Push to packagecloud.io - name: Push to packagecloud.io
if: (github.event_name == 'release' && !github.event.release.prerelease) || inputs.publish_release_artefacts if: (github.event_name == 'release' && !github.event.release.prerelease) || inputs.publish_release_artifacts
env: env:
PROFILE: ${{ steps.profile.outputs.profile }} PROFILE: ${{ steps.profile.outputs.profile }}
VERSION: ${{ steps.profile.outputs.version }} VERSION: ${{ steps.profile.outputs.version }}
@ -106,16 +106,12 @@ jobs:
push "debian/bullseye" "packages/$PROFILE-$VERSION-debian11-arm64.deb" push "debian/bullseye" "packages/$PROFILE-$VERSION-debian11-arm64.deb"
push "debian/bookworm" "packages/$PROFILE-$VERSION-debian12-amd64.deb" push "debian/bookworm" "packages/$PROFILE-$VERSION-debian12-amd64.deb"
push "debian/bookworm" "packages/$PROFILE-$VERSION-debian12-arm64.deb" push "debian/bookworm" "packages/$PROFILE-$VERSION-debian12-arm64.deb"
push "ubuntu/bionic" "packages/$PROFILE-$VERSION-ubuntu18.04-amd64.deb"
push "ubuntu/bionic" "packages/$PROFILE-$VERSION-ubuntu18.04-arm64.deb"
push "ubuntu/focal" "packages/$PROFILE-$VERSION-ubuntu20.04-amd64.deb" push "ubuntu/focal" "packages/$PROFILE-$VERSION-ubuntu20.04-amd64.deb"
push "ubuntu/focal" "packages/$PROFILE-$VERSION-ubuntu20.04-arm64.deb" push "ubuntu/focal" "packages/$PROFILE-$VERSION-ubuntu20.04-arm64.deb"
push "ubuntu/jammy" "packages/$PROFILE-$VERSION-ubuntu22.04-amd64.deb" push "ubuntu/jammy" "packages/$PROFILE-$VERSION-ubuntu22.04-amd64.deb"
push "ubuntu/jammy" "packages/$PROFILE-$VERSION-ubuntu22.04-arm64.deb" push "ubuntu/jammy" "packages/$PROFILE-$VERSION-ubuntu22.04-arm64.deb"
push "ubuntu/noble" "packages/$PROFILE-$VERSION-ubuntu24.04-amd64.deb" push "ubuntu/noble" "packages/$PROFILE-$VERSION-ubuntu24.04-amd64.deb"
push "ubuntu/noble" "packages/$PROFILE-$VERSION-ubuntu24.04-arm64.deb" push "ubuntu/noble" "packages/$PROFILE-$VERSION-ubuntu24.04-arm64.deb"
push "el/7" "packages/$PROFILE-$VERSION-el7-amd64.rpm"
push "el/7" "packages/$PROFILE-$VERSION-el7-arm64.rpm"
push "el/8" "packages/$PROFILE-$VERSION-el8-amd64.rpm" push "el/8" "packages/$PROFILE-$VERSION-el8-amd64.rpm"
push "el/8" "packages/$PROFILE-$VERSION-el8-arm64.rpm" push "el/8" "packages/$PROFILE-$VERSION-el8-arm64.rpm"
push "el/9" "packages/$PROFILE-$VERSION-el9-amd64.rpm" push "el/9" "packages/$PROFILE-$VERSION-el9-amd64.rpm"
@ -135,7 +131,7 @@ jobs:
checks: write checks: write
actions: write actions: write
steps: steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: trigger re-run of app versions check on open PRs - name: trigger re-run of app versions check on open PRs
shell: bash shell: bash
env: env:

View File

@ -25,7 +25,7 @@ jobs:
- emqx - emqx
- emqx-enterprise - emqx-enterprise
steps: steps:
- uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with: with:
name: ${{ matrix.profile }} name: ${{ matrix.profile }}
- name: extract artifact - name: extract artifact
@ -39,10 +39,10 @@ jobs:
- name: print erlang log - name: print erlang log
if: failure() if: failure()
run: | run: |
cat _build/${{ matrix.profile }}/rel/emqx/logs/erlang.log.* cat _build/${{ matrix.profile }}/rel/emqx/log/erlang.log.*
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
if: failure() if: failure()
with: with:
name: conftest-logs-${{ matrix.profile }} name: conftest-logs-${{ matrix.profile }}
path: _build/${{ matrix.profile }}/rel/emqx/logs path: _build/${{ matrix.profile }}/rel/emqx/log
retention-days: 7 retention-days: 7

View File

@ -6,13 +6,6 @@ concurrency:
on: on:
workflow_call: workflow_call:
inputs:
version-emqx:
required: true
type: string
version-emqx-enterprise:
required: true
type: string
permissions: permissions:
contents: read contents: read
@ -32,12 +25,17 @@ jobs:
env: env:
EMQX_NAME: ${{ matrix.profile[0] }} EMQX_NAME: ${{ matrix.profile[0] }}
PKG_VSN: ${{ matrix.profile[0] == 'emqx-enterprise' && inputs.version-emqx-enterprise || inputs.version-emqx }}
EMQX_IMAGE_OLD_VERSION_TAG: ${{ matrix.profile[1] }} EMQX_IMAGE_OLD_VERSION_TAG: ${{ matrix.profile[1] }}
steps: steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 - name: Set up environment
id: env
run: |
source env.sh
PKG_VSN=$(docker run --rm -v $(pwd):$(pwd) -w $(pwd) -u $(id -u) "$EMQX_BUILDER" ./pkg-vsn.sh "$EMQX_NAME")
echo "PKG_VSN=$PKG_VSN" >> "$GITHUB_ENV"
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with: with:
name: ${{ env.EMQX_NAME }}-docker name: ${{ env.EMQX_NAME }}-docker
path: /tmp path: /tmp
@ -47,17 +45,16 @@ jobs:
echo "_EMQX_DOCKER_IMAGE_TAG=$_EMQX_DOCKER_IMAGE_TAG" >> $GITHUB_ENV echo "_EMQX_DOCKER_IMAGE_TAG=$_EMQX_DOCKER_IMAGE_TAG" >> $GITHUB_ENV
- name: dashboard tests - name: dashboard tests
working-directory: ./scripts/ui-tests working-directory: ./scripts/ui-tests
env:
EMQX_VERSION: ${{ inputs.version-emqx }}
EMQX_ENTERPRISE_VERSION: ${{ inputs.version-emqx-enterprise }}
run: | run: |
set -eu set -eu
docker compose up --abort-on-container-exit --exit-code-from selenium docker compose up --abort-on-container-exit --exit-code-from selenium
- name: test two nodes cluster with proto_dist=inet_tls in docker - name: test two nodes cluster with proto_dist=inet_tls in docker
run: | run: |
./scripts/test/start-two-nodes-in-docker.sh -P $_EMQX_DOCKER_IMAGE_TAG $EMQX_IMAGE_OLD_VERSION_TAG ## -d 1 means only put node 1 (latest version) behind haproxy
./scripts/test/start-two-nodes-in-docker.sh -d 1 -P $_EMQX_DOCKER_IMAGE_TAG $EMQX_IMAGE_OLD_VERSION_TAG
HTTP_PORT=$(docker inspect --format='{{(index (index .NetworkSettings.Ports "18083/tcp") 0).HostPort}}' haproxy) HTTP_PORT=$(docker inspect --format='{{(index (index .NetworkSettings.Ports "18083/tcp") 0).HostPort}}' haproxy)
./scripts/test/emqx-smoke-test.sh localhost $HTTP_PORT ./scripts/test/emqx-smoke-test.sh localhost $HTTP_PORT
## -c menas 'cleanup'
./scripts/test/start-two-nodes-in-docker.sh -c ./scripts/test/start-two-nodes-in-docker.sh -c
- name: cleanup - name: cleanup
if: always() if: always()
@ -72,8 +69,6 @@ jobs:
shell: bash shell: bash
env: env:
EMQX_NAME: ${{ matrix.profile }} EMQX_NAME: ${{ matrix.profile }}
PKG_VSN: ${{ matrix.profile == 'emqx-enterprise' && inputs.version-emqx-enterprise || inputs.version-emqx }}
_EMQX_TEST_DB_BACKEND: ${{ matrix.cluster_db_backend }}
strategy: strategy:
fail-fast: false fail-fast: false
@ -82,12 +77,20 @@ jobs:
- emqx - emqx
- emqx-enterprise - emqx-enterprise
- emqx-elixir - emqx-elixir
cluster_db_backend:
- mnesia
- rlog
steps: steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 - name: Set up environment
id: env
run: |
source env.sh
if [ "$EMQX_NAME" = "emqx-enterprise" ]; then
_EMQX_TEST_DB_BACKEND='rlog'
else
_EMQX_TEST_DB_BACKEND='mnesia'
fi
PKG_VSN=$(docker run --rm -v $(pwd):$(pwd) -w $(pwd) -u $(id -u) "$EMQX_BUILDER" ./pkg-vsn.sh "$EMQX_NAME")
echo "PKG_VSN=$PKG_VSN" >> "$GITHUB_ENV"
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with: with:
name: ${{ env.EMQX_NAME }}-docker name: ${{ env.EMQX_NAME }}-docker
path: /tmp path: /tmp

View File

@ -37,7 +37,7 @@ jobs:
matrix: ${{ steps.matrix.outputs.matrix }} matrix: ${{ steps.matrix.outputs.matrix }}
skip: ${{ steps.matrix.outputs.skip }} skip: ${{ steps.matrix.outputs.skip }}
steps: steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
fetch-depth: 0 fetch-depth: 0
- name: prepare test matrix - name: prepare test matrix
@ -72,7 +72,7 @@ jobs:
run: run:
shell: bash shell: bash
steps: steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
fetch-depth: 0 fetch-depth: 0
- name: run - name: run
@ -95,7 +95,7 @@ jobs:
echo "Suites: $SUITES" echo "Suites: $SUITES"
./rebar3 as standalone_test ct --name 'test@127.0.0.1' -v --readable=true --suite="$SUITES" ./rebar3 as standalone_test ct --name 'test@127.0.0.1' -v --readable=true --suite="$SUITES"
fi fi
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
if: failure() if: failure()
with: with:
name: logs-emqx-app-tests-${{ matrix.type }} name: logs-emqx-app-tests-${{ matrix.type }}

View File

@ -6,13 +6,6 @@ concurrency:
on: on:
workflow_call: workflow_call:
inputs:
version-emqx:
required: true
type: string
version-emqx-enterprise:
required: true
type: string
permissions: permissions:
contents: read contents: read
@ -25,7 +18,6 @@ jobs:
shell: bash shell: bash
env: env:
EMQX_NAME: ${{ matrix.profile }} EMQX_NAME: ${{ matrix.profile }}
EMQX_TAG: ${{ matrix.profile == 'emqx-enterprise' && inputs.version-emqx-enterprise || inputs.version-emqx }}
REPOSITORY: "emqx/${{ matrix.profile }}" REPOSITORY: "emqx/${{ matrix.profile }}"
strategy: strategy:
@ -42,10 +34,17 @@ jobs:
- ssl1.3 - ssl1.3
- ssl1.2 - ssl1.2
steps: steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
path: source path: source
- uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 - name: Set up environment
id: env
run: |
cd source
source env.sh
PKG_VSN=$(docker run --rm -v $(pwd):$(pwd) -w $(pwd) -u $(id -u) "$EMQX_BUILDER" ./pkg-vsn.sh "$EMQX_NAME")
echo "EMQX_TAG=$PKG_VSN" >> "$GITHUB_ENV"
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with: with:
name: "${{ env.EMQX_NAME }}-docker" name: "${{ env.EMQX_NAME }}-docker"
path: /tmp path: /tmp
@ -165,7 +164,7 @@ jobs:
fi fi
sleep 1; sleep 1;
done done
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
repository: emqx/paho.mqtt.testing repository: emqx/paho.mqtt.testing
ref: develop-5.0 ref: develop-5.0

View File

@ -2,10 +2,6 @@ name: JMeter integration tests
on: on:
workflow_call: workflow_call:
inputs:
version-emqx:
required: true
type: string
permissions: permissions:
contents: read contents: read
@ -16,7 +12,7 @@ jobs:
steps: steps:
- name: Cache Jmeter - name: Cache Jmeter
id: cache-jmeter id: cache-jmeter
uses: actions/cache@ab5e6d0c87105b4c9c2047343972218f562e4319 # v4.0.1 uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
with: with:
path: /tmp/apache-jmeter.tgz path: /tmp/apache-jmeter.tgz
key: apache-jmeter-5.4.3.tgz key: apache-jmeter-5.4.3.tgz
@ -35,7 +31,7 @@ jobs:
else else
wget --no-verbose --no-check-certificate -O /tmp/apache-jmeter.tgz $ARCHIVE_URL wget --no-verbose --no-check-certificate -O /tmp/apache-jmeter.tgz $ARCHIVE_URL
fi fi
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
with: with:
name: apache-jmeter.tgz name: apache-jmeter.tgz
path: /tmp/apache-jmeter.tgz path: /tmp/apache-jmeter.tgz
@ -55,10 +51,23 @@ jobs:
needs: jmeter_artifact needs: jmeter_artifact
steps: steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: ./.github/actions/prepare-jmeter - name: Set up environment
id: env
run: |
source env.sh
PKG_VSN=$(docker run --rm -v $(pwd):$(pwd) -w $(pwd) -u $(id -u) "$EMQX_BUILDER" ./pkg-vsn.sh emqx)
echo "PKG_VSN=$PKG_VSN" >> "$GITHUB_ENV"
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with: with:
version-emqx: ${{ inputs.version-emqx }} name: emqx-docker
path: /tmp
- name: load docker image
shell: bash
run: |
EMQX_DOCKER_IMAGE_TAG=$(docker load < /tmp/emqx-docker-${PKG_VSN}.tar.gz | sed 's/Loaded image: //g')
echo "_EMQX_DOCKER_IMAGE_TAG=$EMQX_DOCKER_IMAGE_TAG" >> $GITHUB_ENV
- uses: ./.github/actions/prepare-jmeter
- name: docker compose up - name: docker compose up
timeout-minutes: 5 timeout-minutes: 5
run: | run: |
@ -86,7 +95,7 @@ jobs:
echo "check logs failed" echo "check logs failed"
exit 1 exit 1
fi fi
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
if: always() if: always()
with: with:
name: jmeter_logs-advanced_feat-${{ matrix.scripts_type }} name: jmeter_logs-advanced_feat-${{ matrix.scripts_type }}
@ -111,10 +120,23 @@ jobs:
needs: jmeter_artifact needs: jmeter_artifact
steps: steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: ./.github/actions/prepare-jmeter - name: Set up environment
id: env
run: |
source env.sh
PKG_VSN=$(docker run --rm -v $(pwd):$(pwd) -w $(pwd) -u $(id -u) "$EMQX_BUILDER" ./pkg-vsn.sh emqx)
echo "PKG_VSN=$PKG_VSN" >> "$GITHUB_ENV"
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with: with:
version-emqx: ${{ inputs.version-emqx }} name: emqx-docker
path: /tmp
- name: load docker image
shell: bash
run: |
EMQX_DOCKER_IMAGE_TAG=$(docker load < /tmp/emqx-docker-${PKG_VSN}.tar.gz | sed 's/Loaded image: //g')
echo "_EMQX_DOCKER_IMAGE_TAG=$EMQX_DOCKER_IMAGE_TAG" >> $GITHUB_ENV
- uses: ./.github/actions/prepare-jmeter
- name: docker compose up - name: docker compose up
timeout-minutes: 5 timeout-minutes: 5
env: env:
@ -153,7 +175,7 @@ jobs:
if: failure() if: failure()
run: | run: |
docker compose -f .ci/docker-compose-file/docker-compose-emqx-cluster.yaml logs --no-color > ./jmeter_logs/emqx.log docker compose -f .ci/docker-compose-file/docker-compose-emqx-cluster.yaml logs --no-color > ./jmeter_logs/emqx.log
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
if: always() if: always()
with: with:
name: jmeter_logs-pgsql_authn_authz-${{ matrix.scripts_type }}_${{ matrix.pgsql_tag }} name: jmeter_logs-pgsql_authn_authz-${{ matrix.scripts_type }}_${{ matrix.pgsql_tag }}
@ -175,10 +197,23 @@ jobs:
needs: jmeter_artifact needs: jmeter_artifact
steps: steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: ./.github/actions/prepare-jmeter - name: Set up environment
id: env
run: |
source env.sh
PKG_VSN=$(docker run --rm -v $(pwd):$(pwd) -w $(pwd) -u $(id -u) "$EMQX_BUILDER" ./pkg-vsn.sh emqx)
echo "PKG_VSN=$PKG_VSN" >> "$GITHUB_ENV"
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with: with:
version-emqx: ${{ inputs.version-emqx }} name: emqx-docker
path: /tmp
- name: load docker image
shell: bash
run: |
EMQX_DOCKER_IMAGE_TAG=$(docker load < /tmp/emqx-docker-${PKG_VSN}.tar.gz | sed 's/Loaded image: //g')
echo "_EMQX_DOCKER_IMAGE_TAG=$EMQX_DOCKER_IMAGE_TAG" >> $GITHUB_ENV
- uses: ./.github/actions/prepare-jmeter
- name: docker compose up - name: docker compose up
timeout-minutes: 5 timeout-minutes: 5
env: env:
@ -213,7 +248,7 @@ jobs:
echo "check logs failed" echo "check logs failed"
exit 1 exit 1
fi fi
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
if: always() if: always()
with: with:
name: jmeter_logs-mysql_authn_authz-${{ matrix.scripts_type }}_${{ matrix.mysql_tag }} name: jmeter_logs-mysql_authn_authz-${{ matrix.scripts_type }}_${{ matrix.mysql_tag }}
@ -231,10 +266,23 @@ jobs:
needs: jmeter_artifact needs: jmeter_artifact
steps: steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: ./.github/actions/prepare-jmeter - name: Set up environment
id: env
run: |
source env.sh
PKG_VSN=$(docker run --rm -v $(pwd):$(pwd) -w $(pwd) -u $(id -u) "$EMQX_BUILDER" ./pkg-vsn.sh emqx)
echo "PKG_VSN=$PKG_VSN" >> "$GITHUB_ENV"
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with: with:
version-emqx: ${{ inputs.version-emqx }} name: emqx-docker
path: /tmp
- name: load docker image
shell: bash
run: |
EMQX_DOCKER_IMAGE_TAG=$(docker load < /tmp/emqx-docker-${PKG_VSN}.tar.gz | sed 's/Loaded image: //g')
echo "_EMQX_DOCKER_IMAGE_TAG=$EMQX_DOCKER_IMAGE_TAG" >> $GITHUB_ENV
- uses: ./.github/actions/prepare-jmeter
- name: docker compose up - name: docker compose up
timeout-minutes: 5 timeout-minutes: 5
run: | run: |
@ -265,7 +313,7 @@ jobs:
echo "check logs failed" echo "check logs failed"
exit 1 exit 1
fi fi
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
if: always() if: always()
with: with:
name: jmeter_logs-JWT_authn-${{ matrix.scripts_type }} name: jmeter_logs-JWT_authn-${{ matrix.scripts_type }}
@ -284,10 +332,23 @@ jobs:
needs: jmeter_artifact needs: jmeter_artifact
steps: steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: ./.github/actions/prepare-jmeter - name: Set up environment
id: env
run: |
source env.sh
PKG_VSN=$(docker run --rm -v $(pwd):$(pwd) -w $(pwd) -u $(id -u) "$EMQX_BUILDER" ./pkg-vsn.sh emqx)
echo "PKG_VSN=$PKG_VSN" >> "$GITHUB_ENV"
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with: with:
version-emqx: ${{ inputs.version-emqx }} name: emqx-docker
path: /tmp
- name: load docker image
shell: bash
run: |
EMQX_DOCKER_IMAGE_TAG=$(docker load < /tmp/emqx-docker-${PKG_VSN}.tar.gz | sed 's/Loaded image: //g')
echo "_EMQX_DOCKER_IMAGE_TAG=$EMQX_DOCKER_IMAGE_TAG" >> $GITHUB_ENV
- uses: ./.github/actions/prepare-jmeter
- name: docker compose up - name: docker compose up
timeout-minutes: 5 timeout-minutes: 5
run: | run: |
@ -309,7 +370,7 @@ jobs:
echo "check logs failed" echo "check logs failed"
exit 1 exit 1
fi fi
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
if: always() if: always()
with: with:
name: jmeter_logs-built_in_database_authn_authz-${{ matrix.scripts_type }} name: jmeter_logs-built_in_database_authn_authz-${{ matrix.scripts_type }}

View File

@ -25,7 +25,7 @@ jobs:
run: run:
shell: bash shell: bash
steps: steps:
- uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with: with:
name: emqx-enterprise name: emqx-enterprise
- name: extract artifact - name: extract artifact
@ -45,7 +45,7 @@ jobs:
run: | run: |
export PROFILE='emqx-enterprise' export PROFILE='emqx-enterprise'
make emqx-enterprise-tgz make emqx-enterprise-tgz
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
name: Upload built emqx and test scenario name: Upload built emqx and test scenario
with: with:
name: relup_tests_emqx_built name: relup_tests_emqx_built
@ -72,10 +72,10 @@ jobs:
run: run:
shell: bash shell: bash
steps: steps:
- uses: erlef/setup-beam@2f0cc07b4b9bea248ae098aba9e1a8a1de5ec24c # v1.17.5 - uses: erlef/setup-beam@b9c58b0450cd832ccdb3c17cc156a47065d2114f # v1.18.1
with: with:
otp-version: 26.2.1 otp-version: 26.2.5
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
repository: hawk/lux repository: hawk/lux
ref: lux-2.8.1 ref: lux-2.8.1
@ -88,7 +88,7 @@ jobs:
./configure ./configure
make make
echo "$(pwd)/bin" >> $GITHUB_PATH echo "$(pwd)/bin" >> $GITHUB_PATH
- uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
name: Download built emqx and test scenario name: Download built emqx and test scenario
with: with:
name: relup_tests_emqx_built name: relup_tests_emqx_built
@ -111,7 +111,7 @@ jobs:
docker logs node2.emqx.io | tee lux_logs/emqx2.log docker logs node2.emqx.io | tee lux_logs/emqx2.log
exit 1 exit 1
fi fi
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
name: Save debug data name: Save debug data
if: failure() if: failure()
with: with:

View File

@ -20,9 +20,6 @@ on:
required: true required: true
type: string type: string
permissions:
contents: read
env: env:
IS_CI: "yes" IS_CI: "yes"
@ -38,37 +35,41 @@ jobs:
defaults: defaults:
run: run:
shell: bash shell: bash
container: "ghcr.io/emqx/emqx-builder/${{ matrix.builder }}:${{ matrix.elixir }}-${{ matrix.otp }}-ubuntu22.04" container: ${{ inputs.builder }}
env:
PROFILE: ${{ matrix.profile }}
ENABLE_COVER_COMPILE: 1
CT_COVER_EXPORT_PREFIX: ${{ matrix.profile }}
permissions:
contents: read
steps: steps:
- uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with: with:
name: ${{ matrix.profile }} name: ${{ matrix.profile }}
- name: extract artifact - name: extract artifact
run: | run: |
unzip -o -q ${{ matrix.profile }}.zip unzip -o -q ${{ matrix.profile }}.zip
git config --global --add safe.directory "$GITHUB_WORKSPACE" git config --global --add safe.directory "$GITHUB_WORKSPACE"
# produces eunit.coverdata # produces eunit.coverdata
- name: eunit - run: make eunit
env:
PROFILE: ${{ matrix.profile }}
ENABLE_COVER_COMPILE: 1
CT_COVER_EXPORT_PREFIX: ${{ matrix.profile }}-${{ matrix.otp }}
run: make eunit
# produces proper.coverdata # produces proper.coverdata
- name: proper - run: make proper
env:
PROFILE: ${{ matrix.profile }}
ENABLE_COVER_COMPILE: 1
CT_COVER_EXPORT_PREFIX: ${{ matrix.profile }}-${{ matrix.otp }}
run: make proper
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - run: make cover
with:
name: coverdata-${{ matrix.profile }}-${{ matrix.otp }} - name: send to coveralls
path: _build/test/cover if: github.repository == 'emqx/emqx'
retention-days: 7 env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: make coveralls
- run: cat rebar3.crashdump
if: failure()
ct_docker: ct_docker:
runs-on: ${{ github.repository_owner == 'emqx' && fromJSON('["self-hosted","ephemeral","linux","x64"]') || 'ubuntu-22.04' }} runs-on: ${{ github.repository_owner == 'emqx' && fromJSON('["self-hosted","ephemeral","linux","x64"]') || 'ubuntu-22.04' }}
@ -82,19 +83,24 @@ jobs:
run: run:
shell: bash shell: bash
env:
PROFILE: ${{ matrix.profile }}
permissions:
contents: read
steps: steps:
- uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with: with:
name: ${{ matrix.profile }} name: ${{ matrix.profile }}
- name: extract artifact - name: extract artifact
run: | run: |
unzip -o -q ${{ matrix.profile }}.zip unzip -o -q ${{ matrix.profile }}.zip
git config --global --add safe.directory "$GITHUB_WORKSPACE"
# produces $PROFILE-<app-name>-<otp-vsn>-sg<suitegroup>.coverdata # produces $PROFILE-<app-name>-<otp-vsn>-sg<suitegroup>.coverdata
- name: run common tests - name: run common tests
env: env:
DOCKER_CT_RUNNER_IMAGE: "ghcr.io/emqx/emqx-builder/${{ matrix.builder }}:${{ matrix.elixir }}-${{ matrix.otp }}-ubuntu22.04" DOCKER_CT_RUNNER_IMAGE: ${{ inputs.builder }}
MONGO_TAG: "5" MONGO_TAG: "5"
MYSQL_TAG: "8" MYSQL_TAG: "8"
PGSQL_TAG: "13" PGSQL_TAG: "13"
@ -103,23 +109,34 @@ jobs:
TDENGINE_TAG: "3.0.2.4" TDENGINE_TAG: "3.0.2.4"
OPENTS_TAG: "9aa7f88" OPENTS_TAG: "9aa7f88"
MINIO_TAG: "RELEASE.2023-03-20T20-16-18Z" MINIO_TAG: "RELEASE.2023-03-20T20-16-18Z"
PROFILE: ${{ matrix.profile }}
SUITEGROUP: ${{ matrix.suitegroup }} SUITEGROUP: ${{ matrix.suitegroup }}
ENABLE_COVER_COMPILE: 1 ENABLE_COVER_COMPILE: 1
CT_COVER_EXPORT_PREFIX: ${{ matrix.profile }}-${{ matrix.otp }}-sg${{ matrix.suitegroup }} CT_COVER_EXPORT_PREFIX: ${{ matrix.profile }}-sg${{ matrix.suitegroup }}
run: ./scripts/ct/run.sh --ci --app ${{ matrix.app }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 run: ./scripts/ct/run.sh --ci --app ${{ matrix.app }} --keep-up
with:
name: coverdata-${{ matrix.profile }}-${{ matrix.prefix }}-${{ matrix.otp }}-sg${{ matrix.suitegroup }} - name: make cover
path: _build/test/cover run: |
retention-days: 7 docker exec -e PROFILE="$PROFILE" -t erlang make cover
- name: send to coveralls
if: github.repository == 'emqx/emqx'
run: |
ls _build/test/cover/*.coverdata || exit 0
docker exec -e PROFILE="$PROFILE" -t erlang make coveralls
- name: rebar3.crashdump
if: failure()
run: cat rebar3.crashdump
- name: compress logs - name: compress logs
if: failure() if: failure()
run: tar -czf logs.tar.gz _build/test/logs run: tar -czf logs.tar.gz _build/test/logs
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
if: failure() if: failure()
with: with:
name: logs-${{ matrix.profile }}-${{ matrix.prefix }}-${{ matrix.otp }}-sg${{ matrix.suitegroup }} name: logs-${{ matrix.profile }}-${{ matrix.prefix }}-sg${{ matrix.suitegroup }}
path: logs.tar.gz path: logs.tar.gz
compression-level: 0 compression-level: 0
retention-days: 7 retention-days: 7
@ -132,13 +149,22 @@ jobs:
matrix: matrix:
include: ${{ fromJson(inputs.ct-host) }} include: ${{ fromJson(inputs.ct-host) }}
container: "ghcr.io/emqx/emqx-builder/${{ matrix.builder }}:${{ matrix.elixir }}-${{ matrix.otp }}-ubuntu22.04" container: ${{ inputs.builder }}
defaults: defaults:
run: run:
shell: bash shell: bash
permissions:
contents: read
env:
PROFILE: ${{ matrix.profile }}
SUITEGROUP: ${{ matrix.suitegroup }}
ENABLE_COVER_COMPILE: 1
CT_COVER_EXPORT_PREFIX: ${{ matrix.profile }}-sg${{ matrix.suitegroup }}
steps: steps:
- uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with: with:
name: ${{ matrix.profile }} name: ${{ matrix.profile }}
- name: extract artifact - name: extract artifact
@ -148,26 +174,29 @@ jobs:
# produces $PROFILE-<app-name>-<otp-vsn>-sg<suitegroup>.coverdata # produces $PROFILE-<app-name>-<otp-vsn>-sg<suitegroup>.coverdata
- name: run common tests - name: run common tests
run: make "${{ matrix.app }}-ct"
- run: make cover
- name: send to coveralls
if: github.repository == 'emqx/emqx'
env: env:
PROFILE: ${{ matrix.profile }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SUITEGROUP: ${{ matrix.suitegroup }}
ENABLE_COVER_COMPILE: 1
CT_COVER_EXPORT_PREFIX: ${{ matrix.profile }}-${{ matrix.otp }}-sg${{ matrix.suitegroup }}
run: | run: |
make "${{ matrix.app }}-ct" ls _build/test/cover/*.coverdata || exit 0
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 make coveralls
with:
name: coverdata-${{ matrix.profile }}-${{ matrix.prefix }}-${{ matrix.otp }}-sg${{ matrix.suitegroup }} - run: cat rebar3.crashdump
path: _build/test/cover if: failure()
if-no-files-found: warn # do not fail if no coverdata found
retention-days: 7
- name: compress logs - name: compress logs
if: failure() if: failure()
run: tar -czf logs.tar.gz _build/test/logs run: tar -czf logs.tar.gz _build/test/logs
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
if: failure() if: failure()
with: with:
name: logs-${{ matrix.profile }}-${{ matrix.prefix }}-${{ matrix.otp }}-sg${{ matrix.suitegroup }} name: logs-${{ matrix.profile }}-${{ matrix.prefix }}-sg${{ matrix.suitegroup }}
path: logs.tar.gz path: logs.tar.gz
compression-level: 0 compression-level: 0
retention-days: 7 retention-days: 7
@ -180,61 +209,18 @@ jobs:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
strategy: strategy:
fail-fast: false fail-fast: false
permissions:
pull-requests: write
steps: steps:
- name: Coveralls finished
if: github.repository == 'emqx/emqx'
uses: coverallsapp/github-action@643bc377ffa44ace6394b2b5d0d3950076de9f63 # v2.3.0
with:
parallel-finished: true
git-branch: ${{ github.ref }}
git-commit: ${{ github.sha }}
- run: echo "All tests passed" - run: echo "All tests passed"
make_cover:
needs:
- eunit_and_proper
- ct
- ct_docker
runs-on: ${{ endsWith(github.repository, '/emqx') && 'ubuntu-22.04' || fromJSON('["self-hosted","ephemeral","linux","x64"]') }}
container: ${{ inputs.builder }}
strategy:
fail-fast: false
matrix:
profile:
- emqx-enterprise
steps:
- uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4
with:
name: ${{ matrix.profile }}
- name: extract artifact
run: |
unzip -o -q ${{ matrix.profile }}.zip
git config --global --add safe.directory "$GITHUB_WORKSPACE"
- uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4
name: download coverdata
with:
pattern: coverdata-${{ matrix.profile }}-*
path: _build/test/cover
merge-multiple: true
- name: make cover
env:
PROFILE: emqx-enterprise
run: make cover
- name: send to coveralls
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PROFILE: emqx-enterprise
run: make coveralls
- name: get coveralls logs
if: failure()
run: cat rebar3.crashdump
# do this in a separate job
upload_coverdata:
needs: make_cover
runs-on: ubuntu-22.04
steps:
- name: Coveralls Finished
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
curl -v -k https://coveralls.io/webhook \
--header "Content-Type: application/json" \
--data "{\"repo_name\":\"$GITHUB_REPOSITORY\",\"repo_token\":\"$GITHUB_TOKEN\",\"payload\":{\"build_num\":$GITHUB_RUN_ID,\"status\":\"done\"}}" || true

View File

@ -16,20 +16,21 @@ permissions: read-all
jobs: jobs:
analysis: analysis:
if: github.repository == 'emqx/emqx'
name: Scorecard analysis name: Scorecard analysis
runs-on: ubuntu-latest runs-on: ubuntu-22.04
permissions: permissions:
security-events: write security-events: write
id-token: write id-token: write
steps: steps:
- name: "Checkout code" - name: "Checkout code"
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
persist-credentials: false persist-credentials: false
- name: "Run analysis" - name: "Run analysis"
uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1 uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0
with: with:
results_file: results.sarif results_file: results.sarif
results_format: sarif results_format: sarif
@ -39,7 +40,7 @@ jobs:
publish_results: true publish_results: true
- name: "Upload artifact" - name: "Upload artifact"
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
with: with:
name: SARIF file name: SARIF file
path: results.sarif path: results.sarif

View File

@ -19,7 +19,7 @@ jobs:
- emqx-enterprise - emqx-enterprise
runs-on: ${{ endsWith(github.repository, '/emqx') && 'ubuntu-22.04' || fromJSON('["self-hosted","ephemeral","linux","x64"]') }} runs-on: ${{ endsWith(github.repository, '/emqx') && 'ubuntu-22.04' || fromJSON('["self-hosted","ephemeral","linux","x64"]') }}
steps: steps:
- uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with: with:
pattern: "${{ matrix.profile }}-schema-dump-*-x64" pattern: "${{ matrix.profile }}-schema-dump-*-x64"
merge-multiple: true merge-multiple: true

View File

@ -13,8 +13,8 @@ permissions:
jobs: jobs:
stale: stale:
if: github.repository_owner == 'emqx' if: github.repository == 'emqx/emqx'
runs-on: ${{ endsWith(github.repository, '/emqx') && 'ubuntu-22.04' || fromJSON('["self-hosted","ephemeral","linux","x64"]') }} runs-on: ubuntu-22.04
permissions: permissions:
issues: write issues: write
pull-requests: none pull-requests: none

View File

@ -28,21 +28,21 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
include: ${{ fromJson(inputs.ct-matrix) }} include: ${{ fromJson(inputs.ct-matrix) }}
container: "ghcr.io/emqx/emqx-builder/${{ matrix.builder }}:${{ matrix.elixir }}-${{ matrix.otp }}-ubuntu22.04" container: "${{ inputs.builder }}"
steps: steps:
- uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with: with:
name: ${{ matrix.profile }} name: ${{ matrix.profile }}
- name: extract artifact - name: extract artifact
run: | run: |
unzip -o -q ${{ matrix.profile }}.zip unzip -o -q ${{ matrix.profile }}.zip
git config --global --add safe.directory "$GITHUB_WORKSPACE" git config --global --add safe.directory "$GITHUB_WORKSPACE"
- uses: actions/cache@ab5e6d0c87105b4c9c2047343972218f562e4319 # v4.0.1 - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
with: with:
path: "emqx_dialyzer_${{ matrix.otp }}_plt" path: "emqx_dialyzer_${{ matrix.profile }}_plt"
key: rebar3-dialyzer-plt-${{ matrix.profile }}-${{ matrix.otp }}-${{ hashFiles('rebar.*', 'apps/*/rebar.*') }} key: rebar3-dialyzer-plt-${{ matrix.profile }}-${{ hashFiles('rebar.*', 'apps/*/rebar.*') }}
restore-keys: | restore-keys: |
rebar3-dialyzer-plt-${{ matrix.profile }}-${{ matrix.otp }}- rebar3-dialyzer-plt-${{ matrix.profile }}-
- run: cat .env | tee -a $GITHUB_ENV - run: cat .env | tee -a $GITHUB_ENV
- name: run static checks - name: run static checks
run: make static_checks run: make static_checks

View File

@ -0,0 +1,88 @@
name: Sync release branch
concurrency:
group: sync-release-branch-${{ github.event_name }}-${{ github.ref }}
cancel-in-progress: true
on:
schedule:
- cron: '0 2 * * *'
workflow_dispatch:
permissions:
contents: read
jobs:
create-pr:
runs-on: ${{ endsWith(github.repository, '/emqx') && 'ubuntu-22.04' || fromJSON('["self-hosted","ephemeral","linux","x64"]') }}
strategy:
fail-fast: false
matrix:
branch:
- release-57
env:
SYNC_BRANCH: ${{ matrix.branch }}
defaults:
run:
shell: bash
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
fetch-depth: 0
- name: create new branch
run: |
set -euxo pipefail
NEW_BRANCH_NAME=sync-${SYNC_BRANCH}-$(date +"%Y%m%d-%H%M%S")
echo "NEW_BRANCH_NAME=${NEW_BRANCH_NAME}" >> $GITHUB_ENV
git config --global user.name "${GITHUB_ACTOR}"
git config --global user.email "${GITHUB_ACTOR}@users.noreply.github.com"
git checkout -b ${NEW_BRANCH_NAME}
git merge origin/${SYNC_BRANCH} 2>&1 | tee merge.log
git push origin ${NEW_BRANCH_NAME}:${NEW_BRANCH_NAME}
- name: create pull request
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euxo pipefail
for pr in $(gh pr list --state open --base master --label sync-release-branch --search "Sync ${SYNC_BRANCH} in:title" --repo ${{ github.repository }} --json number --jq '.[] | .number'); do
gh pr close $pr --repo ${{ github.repository }} --delete-branch || true
done
gh pr create --title "Sync ${SYNC_BRANCH}" --body "Sync ${SYNC_BRANCH}" --base master --head ${NEW_BRANCH_NAME} --label sync-release-branch --repo ${{ github.repository }}
- name: Send notification to Slack
if: failure()
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
run: |
awk '{printf "%s\\n", $0}' merge.log > merge.log.1
cat <<EOF > payload.json
{
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "Automatic sync of ${SYNC_BRANCH} branch failed: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "\`\`\`$(cat merge.log.1)\`\`\`"
}
}
]
}
EOF
curl -X POST -H 'Content-type: application/json' --data @payload.json "$SLACK_WEBHOOK_URL"

View File

@ -23,7 +23,7 @@ jobs:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_DEFAULT_REGION }} aws-region: ${{ secrets.AWS_DEFAULT_REGION }}
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
ref: ${{ github.event.inputs.tag }} ref: ${{ github.event.inputs.tag }}
- name: Detect profile - name: Detect profile

1
.gitignore vendored
View File

@ -78,3 +78,4 @@ rebar-git-cache.tar
.git/ .git/
apps/emqx_utils/src/emqx_variform_parser.erl apps/emqx_utils/src/emqx_variform_parser.erl
apps/emqx_utils/src/emqx_variform_scan.erl apps/emqx_utils/src/emqx_variform_scan.erl
default-profile.mk

View File

@ -1,2 +1,2 @@
erlang 26.2.1-2 erlang 26.2.5-3
elixir 1.15.7-otp-26 elixir 1.15.7-otp-26

View File

@ -6,23 +6,17 @@ endif
REBAR = $(CURDIR)/rebar3 REBAR = $(CURDIR)/rebar3
BUILD = $(CURDIR)/build BUILD = $(CURDIR)/build
SCRIPTS = $(CURDIR)/scripts SCRIPTS = $(CURDIR)/scripts
export EMQX_RELUP ?= true include env.sh
export EMQX_DEFAULT_BUILDER = ghcr.io/emqx/emqx-builder/5.3-5:1.15.7-26.2.1-2-debian12
export EMQX_DEFAULT_RUNNER = public.ecr.aws/debian/debian:12-slim
export EMQX_REL_FORM ?= tgz
export QUICER_DOWNLOAD_FROM_RELEASE = 1
ifeq ($(OS),Windows_NT)
export REBAR_COLOR=none
FIND=/usr/bin/find
else
FIND=find
endif
# Dashboard version # Dashboard version
# from https://github.com/emqx/emqx-dashboard5 # from https://github.com/emqx/emqx-dashboard5
export EMQX_DASHBOARD_VERSION ?= v1.9.0-beta.1 export EMQX_DASHBOARD_VERSION ?= v1.10.0-beta.1
export EMQX_EE_DASHBOARD_VERSION ?= e1.7.0-beta.1 export EMQX_EE_DASHBOARD_VERSION ?= e1.8.0-beta.1
export EMQX_RELUP ?= true
export EMQX_REL_FORM ?= tgz
-include default-profile.mk
PROFILE ?= emqx PROFILE ?= emqx
REL_PROFILES := emqx emqx-enterprise REL_PROFILES := emqx emqx-enterprise
PKG_PROFILES := emqx-pkg emqx-enterprise-pkg PKG_PROFILES := emqx-pkg emqx-enterprise-pkg
@ -34,6 +28,8 @@ CT_COVER_EXPORT_PREFIX ?= $(PROFILE)
export REBAR_GIT_CLONE_OPTIONS += --depth=1 export REBAR_GIT_CLONE_OPTIONS += --depth=1
ELIXIR_COMMON_DEPS := ensure-hex ensure-mix-rebar3 ensure-mix-rebar
.PHONY: default .PHONY: default
default: $(REBAR) $(PROFILE) default: $(REBAR) $(PROFILE)
@ -53,7 +49,8 @@ $(REBAR): .prepare ensure-rebar3
.PHONY: ensure-hex .PHONY: ensure-hex
ensure-hex: ensure-hex:
@mix local.hex --if-missing --force # @mix local.hex --if-missing --force
@mix local.hex 2.0.6 --if-missing --force
.PHONY: ensure-mix-rebar3 .PHONY: ensure-mix-rebar3
ensure-mix-rebar3: $(REBAR) ensure-mix-rebar3: $(REBAR)
@ -63,8 +60,12 @@ ensure-mix-rebar3: $(REBAR)
ensure-mix-rebar: $(REBAR) ensure-mix-rebar: $(REBAR)
@mix local.rebar --if-missing --force @mix local.rebar --if-missing --force
.PHONY: elixir-common-deps
elixir-common-deps: $(ELIXIR_COMMON_DEPS)
.PHONY: mix-deps-get .PHONY: mix-deps-get
mix-deps-get: $(ELIXIR_COMMON_DEPS) mix-deps-get: elixir-common-deps
@mix deps.get @mix deps.get
.PHONY: eunit .PHONY: eunit
@ -194,8 +195,8 @@ $(PROFILES:%=clean-%):
@if [ -d _build/$(@:clean-%=%) ]; then \ @if [ -d _build/$(@:clean-%=%) ]; then \
rm -f rebar.lock; \ rm -f rebar.lock; \
rm -rf _build/$(@:clean-%=%)/rel; \ rm -rf _build/$(@:clean-%=%)/rel; \
$(FIND) _build/$(@:clean-%=%) -name '*.beam' -o -name '*.so' -o -name '*.app' -o -name '*.appup' -o -name '*.o' -o -name '*.d' -type f | xargs rm -f; \ find _build/$(@:clean-%=%) -name '*.beam' -o -name '*.so' -o -name '*.app' -o -name '*.appup' -o -name '*.o' -o -name '*.d' -type f | xargs rm -f; \
$(FIND) _build/$(@:clean-%=%) -type l -delete; \ find _build/$(@:clean-%=%) -type l -delete; \
fi fi
.PHONY: clean-all .PHONY: clean-all
@ -243,7 +244,7 @@ $(foreach zt,$(ALL_ZIPS),$(eval $(call download-relup-packages,$(zt))))
## relup target is to create relup instructions ## relup target is to create relup instructions
.PHONY: $(REL_PROFILES:%=%-relup) .PHONY: $(REL_PROFILES:%=%-relup)
define gen-relup-target define gen-relup-target
$1-relup: $1-relup-downloads $(COMMON_DEPS) $1-relup: $(COMMON_DEPS)
@$(BUILD) $1 relup @$(BUILD) $1 relup
endef endef
ALL_TGZS = $(REL_PROFILES) ALL_TGZS = $(REL_PROFILES)
@ -252,7 +253,7 @@ $(foreach zt,$(ALL_TGZS),$(eval $(call gen-relup-target,$(zt))))
## tgz target is to create a release package .tar.gz with relup ## tgz target is to create a release package .tar.gz with relup
.PHONY: $(REL_PROFILES:%=%-tgz) .PHONY: $(REL_PROFILES:%=%-tgz)
define gen-tgz-target define gen-tgz-target
$1-tgz: $1-relup $1-tgz: $(COMMON_DEPS)
@$(BUILD) $1 tgz @$(BUILD) $1 tgz
endef endef
ALL_TGZS = $(REL_PROFILES) ALL_TGZS = $(REL_PROFILES)
@ -315,10 +316,20 @@ $(foreach tt,$(ALL_ELIXIR_TGZS),$(eval $(call gen-elixir-tgz-target,$(tt))))
.PHONY: fmt .PHONY: fmt
fmt: $(REBAR) fmt: $(REBAR)
@$(SCRIPTS)/erlfmt -w 'apps/*/{src,include,priv,test,integration_test}/**/*.{erl,hrl,app.src,eterm}' @find . \( -name '*.app.src' -o \
@$(SCRIPTS)/erlfmt -w 'apps/*/rebar.config' 'apps/emqx/rebar.config.script' '.ci/fvt_tests/http_server/rebar.config' -name '*.erl' -o \
@$(SCRIPTS)/erlfmt -w 'rebar.config' 'rebar.config.erl' -name '*.hrl' -o \
@$(SCRIPTS)/erlfmt -w 'scripts/*.escript' 'bin/*.escript' 'bin/nodetool' -name 'rebar.config' -o \
-name '*.eterm' -o \
-name '*.escript' \) \
-not -path '*/_build/*' \
-not -path '*/deps/*' \
-not -path '*/_checkouts/*' \
-type f \
| xargs $(SCRIPTS)/erlfmt -w
@$(SCRIPTS)/erlfmt -w 'apps/emqx/rebar.config.script'
@$(SCRIPTS)/erlfmt -w 'elvis.config'
@$(SCRIPTS)/erlfmt -w 'bin/nodetool'
@mix format @mix format
.PHONY: clean-test-cluster-config .PHONY: clean-test-cluster-config

View File

@ -1,3 +1,5 @@
简体中文 | [English](./README.md) | [Русский](./README-RU.md)
# EMQX # EMQX
[![GitHub Release](https://img.shields.io/github/release/emqx/emqx?color=brightgreen&label=Release)](https://github.com/emqx/emqx/releases) [![GitHub Release](https://img.shields.io/github/release/emqx/emqx?color=brightgreen&label=Release)](https://github.com/emqx/emqx/releases)

View File

@ -1,3 +1,5 @@
Русский | [简体中文](./README-CN.md) | [English](./README.md)
# Брокер EMQX # Брокер EMQX
[![GitHub Release](https://img.shields.io/github/release/emqx/emqx?color=brightgreen&label=Release)](https://github.com/emqx/emqx/releases) [![GitHub Release](https://img.shields.io/github/release/emqx/emqx?color=brightgreen&label=Release)](https://github.com/emqx/emqx/releases)

View File

@ -1,3 +1,5 @@
English | [简体中文](./README-CN.md) | [Русский](./README-RU.md)
# EMQX # EMQX
[![GitHub Release](https://img.shields.io/github/release/emqx/emqx?color=brightgreen&label=Release)](https://github.com/emqx/emqx/releases) [![GitHub Release](https://img.shields.io/github/release/emqx/emqx?color=brightgreen&label=Release)](https://github.com/emqx/emqx/releases)

View File

@ -45,6 +45,10 @@
). ).
-define(assertReceive(PATTERN, TIMEOUT), -define(assertReceive(PATTERN, TIMEOUT),
?assertReceive(PATTERN, TIMEOUT, #{})
).
-define(assertReceive(PATTERN, TIMEOUT, EXTRA),
(fun() -> (fun() ->
receive receive
X__V = PATTERN -> X__V X__V = PATTERN -> X__V
@ -54,7 +58,8 @@
{module, ?MODULE}, {module, ?MODULE},
{line, ?LINE}, {line, ?LINE},
{expression, (??PATTERN)}, {expression, (??PATTERN)},
{mailbox, ?drainMailbox()} {mailbox, ?drainMailbox()},
{extra_info, EXTRA}
]} ]}
) )
end end

View File

@ -65,9 +65,20 @@
%% Route %% Route
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
-record(share_dest, {
session_id :: emqx_session:session_id(),
group :: emqx_types:group()
}).
-record(route, { -record(route, {
topic :: binary(), topic :: binary(),
dest :: node() | {binary(), node()} | emqx_session:session_id() dest ::
node()
| {binary(), node()}
| emqx_session:session_id()
%% One session can also have multiple subscriptions to the same topic through different groups
| #share_dest{}
| emqx_external_broker:dest()
}). }).
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
@ -95,4 +106,10 @@
until :: integer() until :: integer()
}). }).
%%--------------------------------------------------------------------
%% Configurations
%%--------------------------------------------------------------------
-define(KIND_REPLICATE, replicate).
-define(KIND_INITIATE, initiate).
-endif. -endif.

View File

@ -0,0 +1,35 @@
%%--------------------------------------------------------------------
%% Copyright (c) 2022, 2024 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 This header contains definitions of durable session metadata
%% keys, that can be consumed by the external code.
-ifndef(EMQX_DURABLE_SESSION_META_HRL).
-define(EMQX_DURABLE_SESSION_META_HRL, true).
%% Session metadata keys:
-define(created_at, created_at).
-define(last_alive_at, last_alive_at).
-define(expiry_interval, expiry_interval).
%% Unique integer used to create unique identities:
-define(last_id, last_id).
%% Connection info (relevent for the dashboard):
-define(peername, peername).
-define(will_message, will_message).
-define(clientinfo, clientinfo).
-define(protocol, protocol).
-define(offline_info, offline_info).
-endif.

View File

@ -25,7 +25,8 @@
-define(HP_AUTHN, 970). -define(HP_AUTHN, 970).
-define(HP_AUTHZ, 960). -define(HP_AUTHZ, 960).
-define(HP_SYS_MSGS, 950). -define(HP_SYS_MSGS, 950).
-define(HP_MSG_VALIDATION, 945). -define(HP_SCHEMA_VALIDATION, 945).
-define(HP_MESSAGE_TRANSFORMATION, 943).
-define(HP_TOPIC_METRICS, 940). -define(HP_TOPIC_METRICS, 940).
-define(HP_RETAINER, 930). -define(HP_RETAINER, 930).
-define(HP_AUTO_SUB, 920). -define(HP_AUTO_SUB, 920).

View File

@ -0,0 +1,258 @@
%%--------------------------------------------------------------------
%% Copyright (c) 2024 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.
%%--------------------------------------------------------------------
-ifndef(EMQX_METRICS_HRL).
-define(EMQX_METRICS_HRL, true).
%% Bytes sent and received
-define(BYTES_METRICS, [
{counter, 'bytes.received', <<"Number of bytes received ">>},
{counter, 'bytes.sent', <<"Number of bytes sent on this connection">>}
]).
%% Packets sent and received
-define(PACKET_METRICS, [
{counter, 'packets.received', <<"Number of received packet">>},
{counter, 'packets.sent', <<"Number of sent packet">>},
{counter, 'packets.connect.received', <<"Number of received CONNECT packet">>},
{counter, 'packets.connack.sent', <<"Number of sent CONNACK packet">>},
{counter, 'packets.connack.error',
<<"Number of received CONNECT packet with unsuccessful connections">>},
{counter, 'packets.connack.auth_error',
<<"Number of received CONNECT packet with failed Authentication">>},
{counter, 'packets.publish.received', <<"Number of received PUBLISH packet">>},
%% PUBLISH packets sent
{counter, 'packets.publish.sent', <<"Number of sent PUBLISH packet">>},
%% PUBLISH packet_id inuse
{counter, 'packets.publish.inuse',
<<"Number of received PUBLISH packet with occupied identifiers">>},
%% PUBLISH failed for error
{counter, 'packets.publish.error',
<<"Number of received PUBLISH packet that cannot be published">>},
%% PUBLISH failed for auth error
{counter, 'packets.publish.auth_error',
<<"Number of received PUBLISH packets with failed the Authorization check">>},
%% PUBLISH(QoS2) packets dropped
{counter, 'packets.publish.dropped',
<<"Number of messages discarded due to the receiving limit">>},
%% PUBACK packets received
{counter, 'packets.puback.received', <<"Number of received PUBACK packet">>},
%% PUBACK packets sent
{counter, 'packets.puback.sent', <<"Number of sent PUBACK packet">>},
%% PUBACK packet_id inuse
{counter, 'packets.puback.inuse',
<<"Number of received PUBACK packet with occupied identifiers">>},
%% PUBACK packets missed
{counter, 'packets.puback.missed', <<"Number of received packet with identifiers.">>},
%% PUBREC packets received
{counter, 'packets.pubrec.received', <<"Number of received PUBREC packet">>},
%% PUBREC packets sent
{counter, 'packets.pubrec.sent', <<"Number of sent PUBREC packet">>},
%% PUBREC packet_id inuse
{counter, 'packets.pubrec.inuse',
<<"Number of received PUBREC packet with occupied identifiers">>},
%% PUBREC packets missed
{counter, 'packets.pubrec.missed',
<<"Number of received PUBREC packet with unknown identifiers">>},
%% PUBREL packets received
{counter, 'packets.pubrel.received', <<"Number of received PUBREL packet">>},
%% PUBREL packets sent
{counter, 'packets.pubrel.sent', <<"Number of sent PUBREL packet">>},
%% PUBREL packets missed
{counter, 'packets.pubrel.missed',
<<"Number of received PUBREC packet with unknown identifiers">>},
%% PUBCOMP packets received
{counter, 'packets.pubcomp.received', <<"Number of received PUBCOMP packet">>},
%% PUBCOMP packets sent
{counter, 'packets.pubcomp.sent', <<"Number of sent PUBCOMP packet">>},
%% PUBCOMP packet_id inuse
{counter, 'packets.pubcomp.inuse',
<<"Number of received PUBCOMP packet with occupied identifiers">>},
%% PUBCOMP packets missed
{counter, 'packets.pubcomp.missed', <<"Number of missed PUBCOMP packet">>},
%% SUBSCRIBE Packets received
{counter, 'packets.subscribe.received', <<"Number of received SUBSCRIBE packet">>},
%% SUBSCRIBE error
{counter, 'packets.subscribe.error',
<<"Number of received SUBSCRIBE packet with failed subscriptions">>},
%% SUBSCRIBE failed for not auth
{counter, 'packets.subscribe.auth_error',
<<"Number of received SUBACK packet with failed Authorization check">>},
%% SUBACK packets sent
{counter, 'packets.suback.sent', <<"Number of sent SUBACK packet">>},
%% UNSUBSCRIBE Packets received
{counter, 'packets.unsubscribe.received', <<"Number of received UNSUBSCRIBE packet">>},
%% UNSUBSCRIBE error
{counter, 'packets.unsubscribe.error',
<<"Number of received UNSUBSCRIBE packet with failed unsubscriptions">>},
%% UNSUBACK Packets sent
{counter, 'packets.unsuback.sent', <<"Number of sent UNSUBACK packet">>},
%% PINGREQ packets received
{counter, 'packets.pingreq.received', <<"Number of received PINGREQ packet">>},
%% PINGRESP Packets sent
{counter, 'packets.pingresp.sent', <<"Number of sent PUBRESP packet">>},
%% DISCONNECT Packets received
{counter, 'packets.disconnect.received', <<"Number of received DISCONNECT packet">>},
%% DISCONNECT Packets sent
{counter, 'packets.disconnect.sent', <<"Number of sent DISCONNECT packet">>},
%% Auth Packets received
{counter, 'packets.auth.received', <<"Number of received AUTH packet">>},
%% Auth Packets sent
{counter, 'packets.auth.sent', <<"Number of sent AUTH packet">>}
]).
%% Messages sent/received and pubsub
-define(MESSAGE_METRICS, [
%% All Messages received
{counter, 'messages.received', <<
"Number of messages received from the client, equal to the sum of "
"messages.qos0.received, messages.qos1.received and messages.qos2.received"
>>},
%% All Messages sent
{counter, 'messages.sent', <<
"Number of messages sent to the client, equal to the sum of "
"messages.qos0.sent, messages.qos1.sent and messages.qos2.sent"
>>},
%% QoS0 Messages received
{counter, 'messages.qos0.received', <<"Number of QoS 0 messages received from clients">>},
%% QoS0 Messages sent
{counter, 'messages.qos0.sent', <<"Number of QoS 0 messages sent to clients">>},
%% QoS1 Messages received
{counter, 'messages.qos1.received', <<"Number of QoS 1 messages received from clients">>},
%% QoS1 Messages sent
{counter, 'messages.qos1.sent', <<"Number of QoS 1 messages sent to clients">>},
%% QoS2 Messages received
{counter, 'messages.qos2.received', <<"Number of QoS 2 messages received from clients">>},
%% QoS2 Messages sent
{counter, 'messages.qos2.sent', <<"Number of QoS 2 messages sent to clients">>},
%% PubSub Metrics
%% Messages Publish
{counter, 'messages.publish',
<<"Number of messages published in addition to system messages">>},
%% Messages dropped due to no subscribers
{counter, 'messages.dropped',
<<"Number of messages dropped before forwarding to the subscription process">>},
%% Messages that failed validations
{counter, 'messages.validation_failed', <<"Number of message validation failed">>},
%% Messages that passed validations
{counter, 'messages.validation_succeeded', <<"Number of message validation successful">>},
%% % Messages that failed transformations
{counter, 'messages.transformation_failed', <<"Number fo message transformation failed">>},
%% % Messages that passed transformations
{counter, 'messages.transformation_succeeded',
<<"Number fo message transformation succeeded">>},
%% QoS2 Messages expired
{counter, 'messages.dropped.await_pubrel_timeout',
<<"Number of messages dropped due to waiting PUBREL timeout">>},
%% Messages dropped
{counter, 'messages.dropped.no_subscribers',
<<"Number of messages dropped due to no subscribers">>},
%% Messages forward
{counter, 'messages.forward', <<"Number of messages forwarded to other nodes">>},
%% Messages delayed
{counter, 'messages.delayed', <<"Number of delay-published messages">>},
%% Messages delivered
{counter, 'messages.delivered',
<<"Number of messages forwarded to the subscription process internally">>},
%% Messages acked
{counter, 'messages.acked', <<"Number of received PUBACK and PUBREC packet">>},
%% Messages persistently stored
{counter, 'messages.persisted', <<"Number of message persisted">>}
]).
%% Delivery metrics
-define(DELIVERY_METRICS, [
%% All Dropped during delivery
{counter, 'delivery.dropped', <<"Total number of discarded messages when sending">>},
%% Dropped due to no_local
{counter, 'delivery.dropped.no_local', <<
"Number of messages that were dropped due to the No Local subscription "
"option when sending"
>>},
%% Dropped due to message too large
{counter, 'delivery.dropped.too_large', <<
"The number of messages that were dropped because the length exceeded "
"the limit when sending"
>>},
%% Dropped qos0 message
{counter, 'delivery.dropped.qos0_msg', <<
"Number of messages with QoS 0 that were dropped because the message "
"queue was full when sending"
>>},
%% Dropped due to queue full
{counter, 'delivery.dropped.queue_full', <<
"Number of messages with a non-zero QoS that were dropped because the "
"message queue was full when sending"
>>},
%% Dropped due to expired
{counter, 'delivery.dropped.expired',
<<"Number of messages dropped due to message expiration on sending">>}
]).
%% Client Lifecircle metrics
-define(CLIENT_METRICS, [
{counter, 'client.connect', <<"Number of client connections">>},
{counter, 'client.connack', <<"Number of CONNACK packet sent">>},
{counter, 'client.connected', <<"Number of successful client connected">>},
{counter, 'client.authenticate', <<"Number of client Authentication">>},
{counter, 'client.auth.anonymous', <<"Number of clients who log in anonymously">>},
{counter, 'client.authorize', <<"Number of Authorization rule checks">>},
{counter, 'client.subscribe', <<"Number of client subscriptions">>},
{counter, 'client.unsubscribe', <<"Number of client unsubscriptions">>},
{counter, 'client.disconnected', <<"Number of client disconnects">>}
]).
%% Session Lifecircle metrics
-define(SESSION_METRICS, [
{counter, 'session.created', <<"Number of sessions created">>},
{counter, 'session.resumed',
<<"Number of sessions resumed because Clean Session or Clean Start is false">>},
{counter, 'session.takenover',
<<"Number of sessions takenover because Clean Session or Clean Start is false">>},
{counter, 'session.discarded',
<<"Number of sessions dropped because Clean Session or Clean Start is true">>},
{counter, 'session.terminated', <<"Number of terminated sessions">>}
]).
%% Statistic metrics for ACL checking
-define(STASTS_ACL_METRICS, [
{counter, 'authorization.allow', <<"Number of Authorization allow">>},
{counter, 'authorization.deny', <<"Number of Authorization deny">>},
{counter, 'authorization.cache_hit', <<"Number of Authorization hits the cache">>},
{counter, 'authorization.cache_miss', <<"Number of Authorization cache missing">>}
]).
%% Statistic metrics for auth checking
-define(STASTS_AUTHN_METRICS, [
{counter, 'authentication.success', <<"Number of successful client Authentication">>},
{counter, 'authentication.success.anonymous',
<<"Number of successful client Authentication due to anonymous">>},
{counter, 'authentication.failure', <<"Number of failed client Authentication">>}
]).
%% Overload protection counters
-define(OLP_METRICS, [
{counter, 'overload_protection.delay.ok', <<"Number of overload protection delayed">>},
{counter, 'overload_protection.delay.timeout',
<<"Number of overload protection delay timeout">>},
{counter, 'overload_protection.hibernation', <<"Number of overload protection hibernation">>},
{counter, 'overload_protection.gc', <<"Number of overload protection garbage collection">>},
{counter, 'overload_protection.new_conn',
<<"Number of overload protection close new incoming connection">>}
]).
-endif.

View File

@ -683,6 +683,7 @@ end).
-define(FRAME_PARSE_ERROR, frame_parse_error). -define(FRAME_PARSE_ERROR, frame_parse_error).
-define(FRAME_SERIALIZE_ERROR, frame_serialize_error). -define(FRAME_SERIALIZE_ERROR, frame_serialize_error).
-define(THROW_FRAME_ERROR(Reason), erlang:throw({?FRAME_PARSE_ERROR, Reason})). -define(THROW_FRAME_ERROR(Reason), erlang:throw({?FRAME_PARSE_ERROR, Reason})).
-define(THROW_SERIALIZE_ERROR(Reason), erlang:throw({?FRAME_SERIALIZE_ERROR, Reason})). -define(THROW_SERIALIZE_ERROR(Reason), erlang:throw({?FRAME_SERIALIZE_ERROR, Reason})).

View File

@ -0,0 +1,29 @@
%%--------------------------------------------------------------------
%% Copyright (c) 2024 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.
%%--------------------------------------------------------------------
-ifndef(EMQX_PERSISTENT_MESSAGE_HRL).
-define(EMQX_PERSISTENT_MESSAGE_HRL, true).
-define(PERSISTENT_MESSAGE_DB, messages).
-define(PERSISTENCE_ENABLED, emqx_message_persistence_enabled).
-define(WITH_DURABILITY_ENABLED(DO),
case is_persistence_enabled() of
true -> DO;
false -> {skipped, disabled}
end
).
-endif.

View File

@ -28,8 +28,10 @@
%% cert %% cert
-define(VAR_CERT_SUBJECT, "cert_subject"). -define(VAR_CERT_SUBJECT, "cert_subject").
-define(VAR_CERT_CN_NAME, "cert_common_name"). -define(VAR_CERT_CN_NAME, "cert_common_name").
-define(VAR_CERT_PEM, "cert_pem").
-define(PH_CERT_SUBJECT, ?PH(?VAR_CERT_SUBJECT)). -define(PH_CERT_SUBJECT, ?PH(?VAR_CERT_SUBJECT)).
-define(PH_CERT_CN_NAME, ?PH(?VAR_CERT_CN_NAME)). -define(PH_CERT_CN_NAME, ?PH(?VAR_CERT_CN_NAME)).
-define(PH_CERT_PEM, ?PH(?VAR_CERT_PEM)).
%% MQTT/Gateway %% MQTT/Gateway
-define(VAR_PASSWORD, "password"). -define(VAR_PASSWORD, "password").

View File

@ -32,7 +32,7 @@
%% `apps/emqx/src/bpapi/README.md' %% `apps/emqx/src/bpapi/README.md'
%% Opensource edition %% Opensource edition
-define(EMQX_RELEASE_CE, "5.7.0-alpha.1"). -define(EMQX_RELEASE_CE, "5.8.0-alpha.1").
%% Enterprise edition %% Enterprise edition
-define(EMQX_RELEASE_EE, "5.7.0-alpha.1"). -define(EMQX_RELEASE_EE, "5.8.0-alpha.1").

View File

@ -21,4 +21,9 @@
-define(TOMBSTONE_CONFIG_CHANGE_REQ, mark_it_for_deletion). -define(TOMBSTONE_CONFIG_CHANGE_REQ, mark_it_for_deletion).
-define(CONFIG_NOT_FOUND_MAGIC, '$0tFound'). -define(CONFIG_NOT_FOUND_MAGIC, '$0tFound').
%%--------------------------------------------------------------------
%% EE injections
%%--------------------------------------------------------------------
-define(EMQX_SSL_FUN_MFA(Name), {emqx_ssl_fun_mfa, Name}).
-endif. -endif.

View File

@ -20,4 +20,11 @@
-define(IS_SESSION_IMPL_MEM(S), (is_tuple(S) andalso element(1, S) =:= session)). -define(IS_SESSION_IMPL_MEM(S), (is_tuple(S) andalso element(1, S) =:= session)).
-define(IS_SESSION_IMPL_DS(S), (is_map_key(id, S))). -define(IS_SESSION_IMPL_DS(S), (is_map_key(id, S))).
%% (Erlang) messages that a connection process should forward to the
%% session handler.
-record(session_message, {
message :: term()
}).
-define(session_message(MSG), #session_message{message = MSG}).
-endif. -endif.

View File

@ -86,5 +86,6 @@
{'SOURCE_ERROR', <<"Source error">>}, {'SOURCE_ERROR', <<"Source error">>},
{'UPDATE_FAILED', <<"Update failed">>}, {'UPDATE_FAILED', <<"Update failed">>},
{'REST_FAILED', <<"Reset source or config failed">>}, {'REST_FAILED', <<"Reset source or config failed">>},
{'CLIENT_NOT_RESPONSE', <<"Client not responding">>} {'CLIENT_NOT_RESPONSE', <<"Client not responding">>},
{'UNSUPPORTED_MEDIA_TYPE', <<"Unsupported media type">>}
]). ]).

View File

@ -30,7 +30,10 @@
logger:log( logger:log(
Level, Level,
(Data), (Data),
Meta maps:merge(Meta, #{
mfa => {?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY},
line => ?LINE
})
); );
false -> false ->
ok ok
@ -38,16 +41,20 @@
). ).
%% NOTE: do not forget to use atom for msg and add every used msg to %% NOTE: do not forget to use atom for msg and add every used msg to
%% the default value of `log.thorttling.msgs` list. %% the default value of `log.throttling.msgs` list.
-define(SLOG_THROTTLE(Level, Data), -define(SLOG_THROTTLE(Level, Data),
?SLOG_THROTTLE(Level, Data, #{}) ?SLOG_THROTTLE(Level, Data, #{})
). ).
-define(SLOG_THROTTLE(Level, Data, Meta), -define(SLOG_THROTTLE(Level, Data, Meta),
?SLOG_THROTTLE(Level, undefined, Data, Meta)
).
-define(SLOG_THROTTLE(Level, UniqueKey, Data, Meta),
case logger:allow(Level, ?MODULE) of case logger:allow(Level, ?MODULE) of
true -> true ->
(fun(#{msg := __Msg} = __Data) -> (fun(#{msg := __Msg} = __Data) ->
case emqx_log_throttler:allow(__Msg) of case emqx_log_throttler:allow(__Msg, UniqueKey) of
true -> true ->
logger:log(Level, __Data, Meta); logger:log(Level, __Data, Meta);
false -> false ->
@ -84,7 +91,7 @@
?_DO_TRACE(Tag, Msg, Meta), ?_DO_TRACE(Tag, Msg, Meta),
?SLOG( ?SLOG(
Level, Level,
(emqx_trace_formatter:format_meta_map(Meta))#{msg => Msg, tag => Tag}, (Meta)#{msg => Msg, tag => Tag},
#{is_trace => false} #{is_trace => false}
) )
end). end).

View File

@ -25,11 +25,16 @@ all() ->
emqx_common_test_helpers:all(?MODULE). emqx_common_test_helpers:all(?MODULE).
init_per_suite(Config) -> init_per_suite(Config) ->
TCApps = emqx_cth_suite:start( case emqx_ds_test_helpers:skip_if_norepl() of
app_specs(), false ->
#{work_dir => emqx_cth_suite:work_dir(Config)} TCApps = emqx_cth_suite:start(
), app_specs(),
[{tc_apps, TCApps} | Config]. #{work_dir => emqx_cth_suite:work_dir(Config)}
),
[{tc_apps, TCApps} | Config];
Yes ->
Yes
end.
end_per_suite(Config) -> end_per_suite(Config) ->
TCApps = ?config(tc_apps, Config), TCApps = ?config(tc_apps, Config),
@ -56,8 +61,8 @@ init_per_testcase(t_session_gc = TestCase, Config) ->
n => 3, n => 3,
roles => [core, core, core], roles => [core, core, core],
extra_emqx_conf => extra_emqx_conf =>
"\n session_persistence {" "\n durable_sessions {"
"\n last_alive_update_interval = 500ms " "\n heartbeat_interval = 500ms "
"\n session_gc_interval = 1s " "\n session_gc_interval = 1s "
"\n session_gc_batch_size = 2 " "\n session_gc_batch_size = 2 "
"\n }" "\n }"
@ -85,9 +90,11 @@ end_per_testcase(TestCase, Config) when
Nodes = ?config(nodes, Config), Nodes = ?config(nodes, Config),
emqx_common_test_helpers:call_janitor(60_000), emqx_common_test_helpers:call_janitor(60_000),
ok = emqx_cth_cluster:stop(Nodes), ok = emqx_cth_cluster:stop(Nodes),
snabbkaffe:stop(),
ok; ok;
end_per_testcase(_TestCase, _Config) -> end_per_testcase(_TestCase, _Config) ->
emqx_common_test_helpers:call_janitor(60_000), emqx_common_test_helpers:call_janitor(60_000),
snabbkaffe:stop(),
ok. ok.
%%------------------------------------------------------------------------------ %%------------------------------------------------------------------------------
@ -116,7 +123,7 @@ app_specs() ->
app_specs(_Opts = #{}). app_specs(_Opts = #{}).
app_specs(Opts) -> app_specs(Opts) ->
DefaultEMQXConf = "session_persistence {enable = true, renew_streams_interval = 1s}", DefaultEMQXConf = "durable_sessions {enable = true, renew_streams_interval = 1s}",
ExtraEMQXConf = maps:get(extra_emqx_conf, Opts, ""), ExtraEMQXConf = maps:get(extra_emqx_conf, Opts, ""),
[ [
{emqx, DefaultEMQXConf ++ ExtraEMQXConf} {emqx, DefaultEMQXConf ++ ExtraEMQXConf}
@ -156,7 +163,7 @@ mk_clientid(Prefix, ID) ->
restart_node(Node, NodeSpec) -> restart_node(Node, NodeSpec) ->
?tp(will_restart_node, #{}), ?tp(will_restart_node, #{}),
emqx_cth_cluster:restart(Node, NodeSpec), emqx_cth_cluster:restart(NodeSpec),
wait_nodeup(Node), wait_nodeup(Node),
?tp(restarted_node, #{}), ?tp(restarted_node, #{}),
ok. ok.
@ -251,7 +258,7 @@ t_session_subscription_idempotency(Config) ->
ok ok
end, end,
fun(Trace) -> fun(_Trace) ->
Session = session_open(Node1, ClientId), Session = session_open(Node1, ClientId),
?assertMatch( ?assertMatch(
#{SubTopicFilter := #{}}, #{SubTopicFilter := #{}},
@ -324,7 +331,7 @@ t_session_unsubscription_idempotency(Config) ->
ok ok
end, end,
fun(Trace) -> fun(_Trace) ->
Session = session_open(Node1, ClientId), Session = session_open(Node1, ClientId),
?assertEqual( ?assertEqual(
#{}, #{},

74
apps/emqx/mix.exs Normal file
View File

@ -0,0 +1,74 @@
defmodule EMQX.MixProject do
use Mix.Project
alias EMQXUmbrella.MixProject, as: UMP
def project do
[
app: :emqx,
version: "0.1.0",
build_path: "../../_build",
erlc_paths: erlc_paths(),
erlc_options: [
{:i, "src"}
| UMP.erlc_options()
],
compilers: Mix.compilers() ++ [:copy_srcs],
# used by our `Mix.Tasks.Compile.CopySrcs` compiler
extra_dirs: extra_dirs(),
deps_path: "../../deps",
lockfile: "../../mix.lock",
elixir: "~> 1.14",
start_permanent: Mix.env() == :prod,
deps: deps()
]
end
# Run "mix help compile.app" to learn about applications
def application do
[
## FIXME!!! go though emqx.app.src and add missing stuff...
extra_applications: [:public_key, :ssl, :os_mon, :logger, :mnesia, :sasl] ++ UMP.extra_applications(),
mod: {:emqx_app, []}
]
end
def deps() do
## FIXME!!! go though emqx.app.src and add missing stuff...
[
{:emqx_mix_utils, in_umbrella: true, runtime: false},
{:emqx_utils, in_umbrella: true},
{:emqx_ds_backends, in_umbrella: true},
UMP.common_dep(:gproc),
UMP.common_dep(:gen_rpc),
UMP.common_dep(:ekka),
UMP.common_dep(:esockd),
UMP.common_dep(:cowboy),
UMP.common_dep(:lc),
UMP.common_dep(:hocon),
UMP.common_dep(:ranch),
UMP.common_dep(:bcrypt),
UMP.common_dep(:pbkdf2),
UMP.common_dep(:emqx_http_lib),
] ++ UMP.quicer_dep()
end
defp erlc_paths() do
paths = UMP.erlc_paths()
if UMP.test_env?() do
["integration_test" | paths]
else
paths
end
end
defp extra_dirs() do
dirs = ["src", "etc"]
if UMP.test_env?() do
["test", "integration_test" | dirs]
else
dirs
end
end
end

View File

@ -10,12 +10,14 @@
{emqx_bridge,5}. {emqx_bridge,5}.
{emqx_bridge,6}. {emqx_bridge,6}.
{emqx_broker,1}. {emqx_broker,1}.
{emqx_cluster_link,1}.
{emqx_cm,1}. {emqx_cm,1}.
{emqx_cm,2}. {emqx_cm,2}.
{emqx_cm,3}. {emqx_cm,3}.
{emqx_conf,1}. {emqx_conf,1}.
{emqx_conf,2}. {emqx_conf,2}.
{emqx_conf,3}. {emqx_conf,3}.
{emqx_conf,4}.
{emqx_connector,1}. {emqx_connector,1}.
{emqx_dashboard,1}. {emqx_dashboard,1}.
{emqx_delayed,1}. {emqx_delayed,1}.
@ -25,6 +27,7 @@
{emqx_ds,2}. {emqx_ds,2}.
{emqx_ds,3}. {emqx_ds,3}.
{emqx_ds,4}. {emqx_ds,4}.
{emqx_ds_shared_sub,1}.
{emqx_eviction_agent,1}. {emqx_eviction_agent,1}.
{emqx_eviction_agent,2}. {emqx_eviction_agent,2}.
{emqx_eviction_agent,3}. {emqx_eviction_agent,3}.
@ -47,6 +50,7 @@
{emqx_mgmt_api_plugins,1}. {emqx_mgmt_api_plugins,1}.
{emqx_mgmt_api_plugins,2}. {emqx_mgmt_api_plugins,2}.
{emqx_mgmt_api_plugins,3}. {emqx_mgmt_api_plugins,3}.
{emqx_mgmt_api_relup,1}.
{emqx_mgmt_cluster,1}. {emqx_mgmt_cluster,1}.
{emqx_mgmt_cluster,2}. {emqx_mgmt_cluster,2}.
{emqx_mgmt_cluster,3}. {emqx_mgmt_cluster,3}.
@ -59,11 +63,11 @@
{emqx_node_rebalance_api,1}. {emqx_node_rebalance_api,1}.
{emqx_node_rebalance_api,2}. {emqx_node_rebalance_api,2}.
{emqx_node_rebalance_evacuation,1}. {emqx_node_rebalance_evacuation,1}.
{emqx_node_rebalance_purge,1}.
{emqx_node_rebalance_status,1}. {emqx_node_rebalance_status,1}.
{emqx_node_rebalance_status,2}. {emqx_node_rebalance_status,2}.
{emqx_persistent_session_ds,1}. {emqx_persistent_session_ds,1}.
{emqx_plugins,1}. {emqx_plugins,1}.
{emqx_plugins,2}.
{emqx_prometheus,1}. {emqx_prometheus,1}.
{emqx_prometheus,2}. {emqx_prometheus,2}.
{emqx_resource,1}. {emqx_resource,1}.

View File

@ -24,18 +24,18 @@
{deps, [ {deps, [
{emqx_utils, {path, "../emqx_utils"}}, {emqx_utils, {path, "../emqx_utils"}},
{emqx_durable_storage, {path, "../emqx_durable_storage"}}, {emqx_durable_storage, {path, "../emqx_durable_storage"}},
{emqx_ds_backends, {path, "../emqx_ds_backends"}},
{lc, {git, "https://github.com/emqx/lc.git", {tag, "0.3.2"}}}, {lc, {git, "https://github.com/emqx/lc.git", {tag, "0.3.2"}}},
{gproc, {git, "https://github.com/emqx/gproc", {tag, "0.9.0.1"}}}, {gproc, {git, "https://github.com/emqx/gproc", {tag, "0.9.0.1"}}},
{cowboy, {git, "https://github.com/emqx/cowboy", {tag, "2.9.2"}}}, {cowboy, {git, "https://github.com/emqx/cowboy", {tag, "2.9.2"}}},
{esockd, {git, "https://github.com/emqx/esockd", {tag, "5.11.2"}}}, {esockd, {git, "https://github.com/emqx/esockd", {tag, "5.12.0"}}},
{ekka, {git, "https://github.com/emqx/ekka", {tag, "0.19.3"}}}, {ekka, {git, "https://github.com/emqx/ekka", {tag, "0.19.5"}}},
{gen_rpc, {git, "https://github.com/emqx/gen_rpc", {tag, "3.3.1"}}}, {gen_rpc, {git, "https://github.com/emqx/gen_rpc", {tag, "3.3.1"}}},
{hocon, {git, "https://github.com/emqx/hocon.git", {tag, "0.42.2"}}}, {hocon, {git, "https://github.com/emqx/hocon.git", {tag, "0.43.2"}}},
{emqx_http_lib, {git, "https://github.com/emqx/emqx_http_lib.git", {tag, "0.5.3"}}}, {emqx_http_lib, {git, "https://github.com/emqx/emqx_http_lib.git", {tag, "0.5.3"}}},
{pbkdf2, {git, "https://github.com/emqx/erlang-pbkdf2.git", {tag, "2.0.4"}}}, {pbkdf2, {git, "https://github.com/emqx/erlang-pbkdf2.git", {tag, "2.0.4"}}},
{recon, {git, "https://github.com/ferd/recon", {tag, "2.5.1"}}}, {recon, {git, "https://github.com/ferd/recon", {tag, "2.5.1"}}},
{snabbkaffe, {git, "https://github.com/kafka4beam/snabbkaffe.git", {tag, "1.0.8"}}}, {snabbkaffe, {git, "https://github.com/kafka4beam/snabbkaffe.git", {tag, "1.0.10"}}}
{ra, "2.7.3"}
]}. ]}.
{plugins, [{rebar3_proper, "0.12.1"}, rebar3_path_deps]}. {plugins, [{rebar3_proper, "0.12.1"}, rebar3_path_deps]}.

View File

@ -24,7 +24,8 @@ IsQuicSupp = fun() ->
end, end,
Bcrypt = {bcrypt, {git, "https://github.com/emqx/erlang-bcrypt.git", {tag, "0.6.0"}}}, Bcrypt = {bcrypt, {git, "https://github.com/emqx/erlang-bcrypt.git", {tag, "0.6.0"}}},
Quicer = {quicer, {git, "https://github.com/emqx/quic.git", {tag, "0.0.313"}}}. Quicer =
{quicer, {git, "https://github.com/emqx/quic.git", {tag, "0.0.500"}}}.
Dialyzer = fun(Config) -> Dialyzer = fun(Config) ->
{dialyzer, OldDialyzerConfig} = lists:keyfind(dialyzer, 1, Config), {dialyzer, OldDialyzerConfig} = lists:keyfind(dialyzer, 1, Config),

View File

@ -18,6 +18,8 @@
-type traverse_break_reason() :: over | migrate. -type traverse_break_reason() :: over | migrate.
-type opts() :: #{print_fun => fun((io:format(), [term()]) -> ok)}.
-callback backup_tables() -> [mria:table()]. -callback backup_tables() -> [mria:table()].
%% validate the backup %% validate the backup
@ -31,6 +33,9 @@
-callback migrate_mnesia_backup(tuple()) -> {ok, tuple()} | {error, term()}. -callback migrate_mnesia_backup(tuple()) -> {ok, tuple()} | {error, term()}.
-optional_callbacks([validate_mnesia_backup/1, migrate_mnesia_backup/1]). %% NOTE: currently, this is called only when the table has been restored successfully.
-callback on_backup_table_imported(mria:table(), opts()) -> ok | {error, term()}.
-optional_callbacks([validate_mnesia_backup/1, migrate_mnesia_backup/1, on_backup_table_imported/2]).
-export_type([traverse_break_reason/0]). -export_type([traverse_break_reason/0]).

View File

@ -237,32 +237,38 @@ log_formatter(HandlerName, Conf) ->
_ -> _ ->
conf_get("formatter", Conf) conf_get("formatter", Conf)
end, end,
TsFormat = timstamp_format(Conf), TsFormat = timestamp_format(Conf),
WithMfa = conf_get("with_mfa", Conf),
PayloadEncode = conf_get("payload_encode", Conf, text),
do_formatter( do_formatter(
Format, CharsLimit, SingleLine, TimeOffSet, Depth, TsFormat Format, CharsLimit, SingleLine, TimeOffSet, Depth, TsFormat, WithMfa, PayloadEncode
). ).
%% auto | epoch | rfc3339 %% auto | epoch | rfc3339
timstamp_format(Conf) -> timestamp_format(Conf) ->
conf_get("timestamp_format", Conf). conf_get("timestamp_format", Conf).
%% helpers %% helpers
do_formatter(json, CharsLimit, SingleLine, TimeOffSet, Depth, TsFormat) -> do_formatter(json, CharsLimit, SingleLine, TimeOffSet, Depth, TsFormat, WithMfa, PayloadEncode) ->
{emqx_logger_jsonfmt, #{ {emqx_logger_jsonfmt, #{
chars_limit => CharsLimit, chars_limit => CharsLimit,
single_line => SingleLine, single_line => SingleLine,
time_offset => TimeOffSet, time_offset => TimeOffSet,
depth => Depth, depth => Depth,
timestamp_format => TsFormat timestamp_format => TsFormat,
with_mfa => WithMfa,
payload_encode => PayloadEncode
}}; }};
do_formatter(text, CharsLimit, SingleLine, TimeOffSet, Depth, TsFormat) -> do_formatter(text, CharsLimit, SingleLine, TimeOffSet, Depth, TsFormat, WithMfa, PayloadEncode) ->
{emqx_logger_textfmt, #{ {emqx_logger_textfmt, #{
template => ["[", level, "] ", msg, "\n"], template => ["[", level, "] ", msg, "\n"],
chars_limit => CharsLimit, chars_limit => CharsLimit,
single_line => SingleLine, single_line => SingleLine,
time_offset => TimeOffSet, time_offset => TimeOffSet,
depth => Depth, depth => Depth,
timestamp_format => TsFormat timestamp_format => TsFormat,
with_mfa => WithMfa,
payload_encode => PayloadEncode
}}. }}.
%% Don't record all logger message %% Don't record all logger message

View File

@ -20,6 +20,7 @@
%% API %% API
-export([add_handler/0, remove_handler/0, pre_config_update/3]). -export([add_handler/0, remove_handler/0, pre_config_update/3]).
-export([is_olp_enabled/0]). -export([is_olp_enabled/0]).
-export([assert_zone_exists/1]).
-define(ZONES, [zones]). -define(ZONES, [zones]).
@ -44,3 +45,26 @@ is_olp_enabled() ->
false, false,
emqx_config:get([zones], #{}) emqx_config:get([zones], #{})
). ).
-spec assert_zone_exists(binary() | atom()) -> ok.
assert_zone_exists(Name0) when is_binary(Name0) ->
%% an existing zone must have already an atom-name
Name =
try
binary_to_existing_atom(Name0)
catch
_:_ ->
throw({unknown_zone, Name0})
end,
assert_zone_exists(Name);
assert_zone_exists(default) ->
%% there is always a 'default' zone
ok;
assert_zone_exists(Name) when is_atom(Name) ->
try
_ = emqx_config:get([zones, Name]),
ok
catch
error:{config_not_found, _} ->
throw({unknown_zone, Name})
end.

View File

@ -2,7 +2,7 @@
{application, emqx, [ {application, emqx, [
{id, "emqx"}, {id, "emqx"},
{description, "EMQX Core"}, {description, "EMQX Core"},
{vsn, "5.3.0"}, {vsn, "5.3.4"},
{modules, []}, {modules, []},
{registered, []}, {registered, []},
{applications, [ {applications, [
@ -18,7 +18,7 @@
sasl, sasl,
lc, lc,
hocon, hocon,
emqx_durable_storage, emqx_ds_backends,
bcrypt, bcrypt,
pbkdf2, pbkdf2,
emqx_http_lib, emqx_http_lib,

View File

@ -61,9 +61,12 @@
get_raw_config/2, get_raw_config/2,
update_config/2, update_config/2,
update_config/3, update_config/3,
update_config/4,
remove_config/1, remove_config/1,
remove_config/2, remove_config/2,
remove_config/3,
reset_config/2, reset_config/2,
reset_config/3,
data_dir/0, data_dir/0,
etc_file/1, etc_file/1,
cert_file/1, cert_file/1,
@ -195,7 +198,7 @@ get_raw_config(KeyPath, Default) ->
-spec update_config(emqx_utils_maps:config_key_path(), emqx_config:update_request()) -> -spec update_config(emqx_utils_maps:config_key_path(), emqx_config:update_request()) ->
{ok, emqx_config:update_result()} | {error, emqx_config:update_error()}. {ok, emqx_config:update_result()} | {error, emqx_config:update_error()}.
update_config(KeyPath, UpdateReq) -> update_config(KeyPath, UpdateReq) ->
update_config(KeyPath, UpdateReq, #{}). update_config(KeyPath, UpdateReq, #{}, #{}).
-spec update_config( -spec update_config(
emqx_utils_maps:config_key_path(), emqx_utils_maps:config_key_path(),
@ -203,30 +206,56 @@ update_config(KeyPath, UpdateReq) ->
emqx_config:update_opts() emqx_config:update_opts()
) -> ) ->
{ok, emqx_config:update_result()} | {error, emqx_config:update_error()}. {ok, emqx_config:update_result()} | {error, emqx_config:update_error()}.
update_config([RootName | _] = KeyPath, UpdateReq, Opts) -> update_config(KeyPath, UpdateReq, Opts) ->
update_config(KeyPath, UpdateReq, Opts, #{}).
-spec update_config(
emqx_utils_maps:config_key_path(),
emqx_config:update_request(),
emqx_config:update_opts(),
emqx_config:cluster_rpc_opts()
) ->
{ok, emqx_config:update_result()} | {error, emqx_config:update_error()}.
update_config([RootName | _] = KeyPath, UpdateReq, Opts, ClusterRpcOpts) ->
emqx_config_handler:update_config( emqx_config_handler:update_config(
emqx_config:get_schema_mod(RootName), emqx_config:get_schema_mod(RootName),
KeyPath, KeyPath,
{{update, UpdateReq}, Opts} {{update, UpdateReq}, Opts},
ClusterRpcOpts
). ).
-spec remove_config(emqx_utils_maps:config_key_path()) -> -spec remove_config(emqx_utils_maps:config_key_path()) ->
{ok, emqx_config:update_result()} | {error, emqx_config:update_error()}. {ok, emqx_config:update_result()} | {error, emqx_config:update_error()}.
remove_config(KeyPath) -> remove_config(KeyPath) ->
remove_config(KeyPath, #{}). remove_config(KeyPath, #{}, #{}).
-spec remove_config(emqx_utils_maps:config_key_path(), emqx_config:update_opts()) -> -spec remove_config(emqx_utils_maps:config_key_path(), emqx_config:update_opts()) ->
{ok, emqx_config:update_result()} | {error, emqx_config:update_error()}. {ok, emqx_config:update_result()} | {error, emqx_config:update_error()}.
remove_config([RootName | _] = KeyPath, Opts) -> remove_config([_RootName | _] = KeyPath, Opts) ->
remove_config(KeyPath, Opts, #{}).
-spec remove_config(
emqx_utils_maps:config_key_path(), emqx_config:update_opts(), emqx_config:cluster_rpc_opts()
) ->
{ok, emqx_config:update_result()} | {error, emqx_config:update_error()}.
remove_config([RootName | _] = KeyPath, Opts, ClusterRpcOpts) ->
emqx_config_handler:update_config( emqx_config_handler:update_config(
emqx_config:get_schema_mod(RootName), emqx_config:get_schema_mod(RootName),
KeyPath, KeyPath,
{remove, Opts} {remove, Opts},
ClusterRpcOpts
). ).
-spec reset_config(emqx_utils_maps:config_key_path(), emqx_config:update_opts()) -> -spec reset_config(emqx_utils_maps:config_key_path(), emqx_config:update_opts()) ->
{ok, emqx_config:update_result()} | {error, emqx_config:update_error()}. {ok, emqx_config:update_result()} | {error, emqx_config:update_error()}.
reset_config([RootName | SubKeys] = KeyPath, Opts) -> reset_config([RootName | SubKeys] = KeyPath, Opts) ->
reset_config([RootName | SubKeys] = KeyPath, Opts, #{}).
-spec reset_config(
emqx_utils_maps:config_key_path(), emqx_config:update_opts(), emqx_config:cluster_rpc_opts()
) ->
{ok, emqx_config:update_result()} | {error, emqx_config:update_error()}.
reset_config([RootName | SubKeys] = KeyPath, Opts, ClusterRpcOpts) ->
case emqx_config:get_default_value(KeyPath) of case emqx_config:get_default_value(KeyPath) of
{ok, Default} -> {ok, Default} ->
Mod = emqx_config:get_schema_mod(RootName), Mod = emqx_config:get_schema_mod(RootName),
@ -235,7 +264,8 @@ reset_config([RootName | SubKeys] = KeyPath, Opts) ->
emqx_config_handler:update_config( emqx_config_handler:update_config(
Mod, Mod,
KeyPath, KeyPath,
{{update, Default}, Opts} {{update, Default}, Opts},
ClusterRpcOpts
); );
false -> false ->
NewConf = NewConf =
@ -247,7 +277,8 @@ reset_config([RootName | SubKeys] = KeyPath, Opts) ->
emqx_config_handler:update_config( emqx_config_handler:update_config(
Mod, Mod,
[RootName], [RootName],
{{update, NewConf}, Opts} {{update, NewConf}, Opts},
ClusterRpcOpts
) )
end; end;
{error, _} = Error -> {error, _} = Error ->

View File

@ -56,31 +56,31 @@ authenticate(Credential) ->
NotSuperUser = #{is_superuser => false}, NotSuperUser = #{is_superuser => false},
case pre_hook_authenticate(Credential) of case pre_hook_authenticate(Credential) of
ok -> ok ->
inc_authn_metrics(anonymous), on_authentication_complete(Credential, NotSuperUser, anonymous),
{ok, NotSuperUser}; {ok, NotSuperUser};
continue -> continue ->
case run_hooks('client.authenticate', [Credential], ignore) of case run_hooks('client.authenticate', [Credential], ignore) of
ignore -> ignore ->
inc_authn_metrics(anonymous), on_authentication_complete(Credential, NotSuperUser, anonymous),
{ok, NotSuperUser}; {ok, NotSuperUser};
ok -> ok ->
inc_authn_metrics(ok), on_authentication_complete(Credential, NotSuperUser, ok),
{ok, NotSuperUser}; {ok, NotSuperUser};
{ok, _AuthResult} = OkResult -> {ok, AuthResult} = OkResult ->
inc_authn_metrics(ok), on_authentication_complete(Credential, AuthResult, ok),
OkResult; OkResult;
{ok, _AuthResult, _AuthData} = OkResult -> {ok, AuthResult, _AuthData} = OkResult ->
inc_authn_metrics(ok), on_authentication_complete(Credential, AuthResult, ok),
OkResult; OkResult;
{error, _Reason} = Error -> {error, Reason} = Error ->
inc_authn_metrics(error), on_authentication_complete(Credential, Reason, error),
Error; Error;
%% {continue, AuthCache} | {continue, AuthData, AuthCache} %% {continue, AuthCache} | {continue, AuthData, AuthCache}
Other -> Other ->
Other Other
end; end;
{error, _Reason} = Error -> {error, Reason} = Error ->
inc_authn_metrics(error), on_authentication_complete(Credential, Reason, error),
Error Error
end. end.
@ -238,5 +238,30 @@ inc_authn_metrics(error) ->
inc_authn_metrics(ok) -> inc_authn_metrics(ok) ->
emqx_metrics:inc('authentication.success'); emqx_metrics:inc('authentication.success');
inc_authn_metrics(anonymous) -> inc_authn_metrics(anonymous) ->
emqx_metrics:inc('client.auth.anonymous'),
emqx_metrics:inc('authentication.success.anonymous'), emqx_metrics:inc('authentication.success.anonymous'),
emqx_metrics:inc('authentication.success'). emqx_metrics:inc('authentication.success').
on_authentication_complete(Credential, Reason, error) ->
emqx_hooks:run(
'client.check_authn_complete',
[
Credential,
#{
reason_code => Reason
}
]
),
inc_authn_metrics(error);
on_authentication_complete(Credential, Result, Type) ->
emqx_hooks:run(
'client.check_authn_complete',
[
Credential,
Result#{
reason_code => success,
is_anonymous => (Type =:= anonymous)
}
]
),
inc_authn_metrics(Type).

View File

@ -16,6 +16,8 @@
-module(emqx_banned). -module(emqx_banned).
-feature(maybe_expr, enable).
-behaviour(gen_server). -behaviour(gen_server).
-behaviour(emqx_db_backup). -behaviour(emqx_db_backup).
@ -31,6 +33,7 @@
-export([ -export([
check/1, check/1,
check_clientid/1,
create/1, create/1,
look_up/1, look_up/1,
delete/1, delete/1,
@ -48,6 +51,7 @@
handle_call/3, handle_call/3,
handle_cast/2, handle_cast/2,
handle_info/2, handle_info/2,
handle_continue/2,
terminate/2, terminate/2,
code_change/3 code_change/3
]). ]).
@ -114,6 +118,10 @@ check(ClientInfo) ->
do_check({peerhost, maps:get(peerhost, ClientInfo, undefined)}) orelse do_check({peerhost, maps:get(peerhost, ClientInfo, undefined)}) orelse
do_check_rules(ClientInfo). do_check_rules(ClientInfo).
-spec check_clientid(emqx_types:clientid()) -> boolean().
check_clientid(ClientId) ->
do_check({clientid, ClientId}) orelse do_check_rules(#{clientid => ClientId}).
-spec format(emqx_types:banned()) -> map(). -spec format(emqx_types:banned()) -> map().
format(#banned{ format(#banned{
who = Who0, who = Who0,
@ -132,7 +140,7 @@ format(#banned{
until => to_rfc3339(Until) until => to_rfc3339(Until)
}. }.
-spec parse(map()) -> emqx_types:banned() | {error, term()}. -spec parse(map()) -> {ok, emqx_types:banned()} | {error, term()}.
parse(Params) -> parse(Params) ->
case parse_who(Params) of case parse_who(Params) of
{error, Reason} -> {error, Reason} ->
@ -144,13 +152,13 @@ parse(Params) ->
Until = maps:get(<<"until">>, Params, At + ?EXPIRATION_TIME), Until = maps:get(<<"until">>, Params, At + ?EXPIRATION_TIME),
case Until > erlang:system_time(second) of case Until > erlang:system_time(second) of
true -> true ->
#banned{ {ok, #banned{
who = Who, who = Who,
by = By, by = By,
reason = Reason, reason = Reason,
at = At, at = At,
until = Until until = Until
}; }};
false -> false ->
ErrorReason = ErrorReason =
io_lib:format("Cannot create expired banned, ~p to ~p", [At, Until]), io_lib:format("Cannot create expired banned, ~p to ~p", [At, Until]),
@ -234,12 +242,139 @@ who(peerhost_net, CIDR) when is_tuple(CIDR) -> {peerhost_net, CIDR};
who(peerhost_net, CIDR) when is_binary(CIDR) -> who(peerhost_net, CIDR) when is_binary(CIDR) ->
{peerhost_net, esockd_cidr:parse(binary_to_list(CIDR), true)}. {peerhost_net, esockd_cidr:parse(binary_to_list(CIDR), true)}.
%%--------------------------------------------------------------------
%% Import From CSV
%%--------------------------------------------------------------------
init_from_csv(undefined) ->
ok;
init_from_csv(File) ->
maybe
core ?= mria_rlog:role(),
'$end_of_table' ?= mnesia:dirty_first(?BANNED_RULE_TAB),
'$end_of_table' ?= mnesia:dirty_first(?BANNED_INDIVIDUAL_TAB),
{ok, Bin} ?= file:read_file(File),
Stream = emqx_utils_stream:csv(Bin, #{nullable => true, filter_null => true}),
{ok, List} ?= parse_stream(Stream),
import_from_stream(List),
?SLOG(info, #{
msg => "load_banned_bootstrap_file_succeeded",
file => File
})
else
replicant ->
ok;
{Name, _} when
Name == peerhost;
Name == peerhost_net;
Name == clientid_re;
Name == username_re;
Name == clientid;
Name == username
->
ok;
{error, Reason} = Error ->
?SLOG(error, #{
msg => "load_banned_bootstrap_file_failed",
reason => Reason,
file => File
}),
Error
end.
import_from_stream(Stream) ->
Groups = maps:groups_from_list(
fun(#banned{who = Who}) -> table(Who) end, Stream
),
maps:foreach(
fun(Tab, Items) ->
Trans = fun() ->
lists:foreach(
fun(Item) ->
mnesia:write(Tab, Item, write)
end,
Items
)
end,
case trans(Trans) of
{ok, _} ->
?SLOG(info, #{
msg => "import_banned_from_stream_succeeded",
items => Items
});
{error, Reason} ->
?SLOG(error, #{
msg => "import_banned_from_stream_failed",
reason => Reason,
items => Items
})
end
end,
Groups
).
parse_stream(Stream) ->
try
List = emqx_utils_stream:consume(Stream),
parse_stream(List, [], [])
catch
error:Reason ->
{error, Reason}
end.
parse_stream([Item | List], Ok, Error) ->
maybe
{ok, Item1} ?= normalize_parse_item(Item),
{ok, Banned} ?= parse(Item1),
parse_stream(List, [Banned | Ok], Error)
else
{error, _} ->
parse_stream(List, Ok, [Item | Error])
end;
parse_stream([], Ok, []) ->
{ok, Ok};
parse_stream([], Ok, Error) ->
?SLOG(warning, #{
msg => "invalid_banned_items",
items => Error
}),
{ok, Ok}.
normalize_parse_item(#{<<"as">> := As} = Item) ->
ParseTime = fun(Name, Input) ->
maybe
#{Name := Time} ?= Input,
{ok, Epoch} ?= emqx_utils_calendar:to_epoch_second(emqx_utils_conv:str(Time)),
{ok, Input#{Name := Epoch}}
else
{error, _} = Error ->
Error;
NoTime when is_map(NoTime) ->
{ok, NoTime}
end
end,
maybe
{ok, Type} ?= emqx_utils:safe_to_existing_atom(As),
{ok, Item1} ?= ParseTime(<<"at">>, Item#{<<"as">> := Type}),
ParseTime(<<"until">>, Item1)
end;
normalize_parse_item(_Item) ->
{error, invalid_item}.
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% gen_server callbacks %% gen_server callbacks
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
init([]) -> init([]) ->
{ok, ensure_expiry_timer(#{expiry_timer => undefined})}. {ok, ensure_expiry_timer(#{expiry_timer => undefined}), {continue, init_from_csv}}.
handle_continue(init_from_csv, State) ->
File = emqx_schema:naive_env_interpolation(
emqx:get_config([banned, bootstrap_file], undefined)
),
_ = init_from_csv(File),
{noreply, State}.
handle_call(Req, _From, State) -> handle_call(Req, _From, State) ->
?SLOG(error, #{msg => "unexpected_call", call => Req}), ?SLOG(error, #{msg => "unexpected_call", call => Req}),
@ -250,7 +385,7 @@ handle_cast(Msg, State) ->
{noreply, State}. {noreply, State}.
handle_info({timeout, TRef, expire}, State = #{expiry_timer := TRef}) -> handle_info({timeout, TRef, expire}, State = #{expiry_timer := TRef}) ->
_ = mria:transaction(?COMMON_SHARD, fun ?MODULE:expire_banned_items/1, [ _ = trans(fun ?MODULE:expire_banned_items/1, [
erlang:system_time(second) erlang:system_time(second)
]), ]),
{noreply, ensure_expiry_timer(State), hibernate}; {noreply, ensure_expiry_timer(State), hibernate};
@ -391,3 +526,15 @@ on_banned(_) ->
all_rules() -> all_rules() ->
ets:tab2list(?BANNED_RULE_TAB). ets:tab2list(?BANNED_RULE_TAB).
trans(Fun) ->
case mria:transaction(?COMMON_SHARD, Fun) of
{atomic, Res} -> {ok, Res};
{aborted, Reason} -> {error, Reason}
end.
trans(Fun, Args) ->
case mria:transaction(?COMMON_SHARD, Fun, Args) of
{atomic, Res} -> {ok, Res};
{aborted, Reason} -> {error, Reason}
end.

View File

@ -244,11 +244,24 @@ publish(Msg) when is_record(Msg, message) ->
topic => Topic topic => Topic
}), }),
[]; [];
Msg1 = #message{topic = Topic} -> Msg1 = #message{} ->
PersistRes = persist_publish(Msg1), do_publish(Msg1);
route(aggre(emqx_router:match_routes(Topic)), delivery(Msg1), PersistRes) Msgs when is_list(Msgs) ->
do_publish_many(Msgs)
end. end.
do_publish_many([]) ->
[];
do_publish_many([Msg | T]) ->
do_publish(Msg) ++ do_publish_many(T).
do_publish(#message{topic = Topic} = Msg) ->
PersistRes = persist_publish(Msg),
Routes = aggre(emqx_router:match_routes(Topic)),
Delivery = delivery(Msg),
RouteRes = route(Routes, Delivery, PersistRes),
do_forward_external(Delivery, RouteRes).
persist_publish(Msg) -> persist_publish(Msg) ->
case emqx_persistent_message:persist(Msg) of case emqx_persistent_message:persist(Msg) of
ok -> ok ->
@ -332,6 +345,9 @@ aggre([], false, Acc) ->
aggre([], true, Acc) -> aggre([], true, Acc) ->
lists:usort(Acc). lists:usort(Acc).
do_forward_external(Delivery, RouteRes) ->
emqx_external_broker:forward(Delivery) ++ RouteRes.
%% @doc Forward message to another node. %% @doc Forward message to another node.
-spec forward( -spec forward(
node(), emqx_types:topic() | emqx_types:share(), emqx_types:delivery(), RpcMode :: sync | async node(), emqx_types:topic() | emqx_types:share(), emqx_types:delivery(), RpcMode :: sync | async
@ -643,19 +659,27 @@ maybe_delete_route(Topic) ->
sync_route(Action, Topic, ReplyTo) -> sync_route(Action, Topic, ReplyTo) ->
EnabledOn = emqx_config:get([broker, routing, batch_sync, enable_on]), EnabledOn = emqx_config:get([broker, routing, batch_sync, enable_on]),
case EnabledOn of Res =
all -> case EnabledOn of
push_sync_route(Action, Topic, ReplyTo); all ->
none -> push_sync_route(Action, Topic, ReplyTo);
regular_sync_route(Action, Topic); none ->
Role -> regular_sync_route(Action, Topic);
case Role =:= mria_config:whoami() of Role ->
true -> case Role =:= mria_config:whoami() of
push_sync_route(Action, Topic, ReplyTo); true ->
false -> push_sync_route(Action, Topic, ReplyTo);
regular_sync_route(Action, Topic) false ->
end regular_sync_route(Action, Topic)
end. end
end,
_ = external_sync_route(Action, Topic),
Res.
external_sync_route(add, Topic) ->
emqx_external_broker:add_route(Topic);
external_sync_route(delete, Topic) ->
emqx_external_broker:delete_route(Topic).
push_sync_route(Action, Topic, Opts) -> push_sync_route(Action, Topic, Opts) ->
emqx_router_syncer:push(Action, Topic, node(), Opts). emqx_router_syncer:push(Action, Topic, node(), Opts).

View File

@ -110,7 +110,12 @@ reclaim_seq(Topic) ->
stats_fun() -> stats_fun() ->
safe_update_stats(subscriber_val(), 'subscribers.count', 'subscribers.max'), safe_update_stats(subscriber_val(), 'subscribers.count', 'subscribers.max'),
safe_update_stats(table_size(?SUBSCRIPTION), 'subscriptions.count', 'subscriptions.max'), safe_update_stats(subscription_count(), 'subscriptions.count', 'subscriptions.max'),
safe_update_stats(
durable_subscription_count(),
'durable_subscriptions.count',
'durable_subscriptions.max'
),
safe_update_stats(table_size(?SUBOPTION), 'suboptions.count', 'suboptions.max'). safe_update_stats(table_size(?SUBOPTION), 'suboptions.count', 'suboptions.max').
safe_update_stats(undefined, _Stat, _MaxStat) -> safe_update_stats(undefined, _Stat, _MaxStat) ->
@ -118,6 +123,14 @@ safe_update_stats(undefined, _Stat, _MaxStat) ->
safe_update_stats(Val, Stat, MaxStat) when is_integer(Val) -> safe_update_stats(Val, Stat, MaxStat) when is_integer(Val) ->
emqx_stats:setstat(Stat, MaxStat, Val). emqx_stats:setstat(Stat, MaxStat, Val).
%% N.B.: subscriptions from durable sessions are not tied to any particular node.
%% Therefore, do not sum them with node-local subscriptions.
subscription_count() ->
table_size(?SUBSCRIPTION).
durable_subscription_count() ->
emqx_persistent_session_bookkeeper:get_subscription_count().
subscriber_val() -> subscriber_val() ->
sum_subscriber(table_size(?SUBSCRIBER), table_size(?SHARED_SUBSCRIBER)). sum_subscriber(table_size(?SUBSCRIBER), table_size(?SHARED_SUBSCRIBER)).

View File

@ -47,7 +47,7 @@ init([]) ->
router_syncer_pool, router_syncer_pool,
hash, hash,
PoolSize, PoolSize,
{emqx_router_syncer, start_link, []} {emqx_router_syncer, start_link_pooled, []}
]), ]),
%% Shared subscription %% Shared subscription

View File

@ -19,6 +19,7 @@
-include("emqx.hrl"). -include("emqx.hrl").
-include("emqx_channel.hrl"). -include("emqx_channel.hrl").
-include("emqx_session.hrl").
-include("emqx_mqtt.hrl"). -include("emqx_mqtt.hrl").
-include("emqx_access_control.hrl"). -include("emqx_access_control.hrl").
-include("logger.hrl"). -include("logger.hrl").
@ -145,7 +146,9 @@
-type replies() :: emqx_types:packet() | reply() | [reply()]. -type replies() :: emqx_types:packet() | reply() | [reply()].
-define(IS_MQTT_V5, #channel{conninfo = #{proto_ver := ?MQTT_PROTO_V5}}). -define(IS_MQTT_V5, #channel{conninfo = #{proto_ver := ?MQTT_PROTO_V5}}).
-define(IS_CONNECTED_OR_REAUTHENTICATING(ConnState),
((ConnState == connected) orelse (ConnState == reauthenticating))
).
-define(IS_COMMON_SESSION_TIMER(N), -define(IS_COMMON_SESSION_TIMER(N),
((N == retry_delivery) orelse (N == expire_awaiting_rel)) ((N == retry_delivery) orelse (N == expire_awaiting_rel))
). ).
@ -234,7 +237,7 @@ caps(#channel{clientinfo = #{zone := Zone}}) ->
-spec init(emqx_types:conninfo(), opts()) -> channel(). -spec init(emqx_types:conninfo(), opts()) -> channel().
init( init(
ConnInfo = #{ ConnInfo = #{
peername := {PeerHost, PeerPort}, peername := {PeerHost, PeerPort} = PeerName,
sockname := {_Host, SockPort} sockname := {_Host, SockPort}
}, },
#{ #{
@ -258,6 +261,9 @@ init(
listener => ListenerId, listener => ListenerId,
protocol => Protocol, protocol => Protocol,
peerhost => PeerHost, peerhost => PeerHost,
%% We copy peername to clientinfo because some event contexts only have access
%% to client info (e.g.: authn/authz).
peername => PeerName,
peerport => PeerPort, peerport => PeerPort,
sockport => SockPort, sockport => SockPort,
clientid => undefined, clientid => undefined,
@ -269,7 +275,7 @@ init(
}, },
Zone Zone
), ),
{NClientInfo, NConnInfo} = take_ws_cookie(ClientInfo, ConnInfo), {NClientInfo, NConnInfo} = take_conn_info_fields([ws_cookie, peersni], ClientInfo, ConnInfo),
#channel{ #channel{
conninfo = NConnInfo, conninfo = NConnInfo,
clientinfo = NClientInfo, clientinfo = NClientInfo,
@ -309,13 +315,19 @@ set_peercert_infos(Peercert, ClientInfo, Zone) ->
ClientId = PeercetAs(peer_cert_as_clientid), ClientId = PeercetAs(peer_cert_as_clientid),
ClientInfo#{username => Username, clientid => ClientId, dn => DN, cn => CN}. ClientInfo#{username => Username, clientid => ClientId, dn => DN, cn => CN}.
take_ws_cookie(ClientInfo, ConnInfo) -> take_conn_info_fields(Fields, ClientInfo, ConnInfo) ->
case maps:take(ws_cookie, ConnInfo) of lists:foldl(
{WsCookie, NConnInfo} -> fun(Field, {ClientInfo0, ConnInfo0}) ->
{ClientInfo#{ws_cookie => WsCookie}, NConnInfo}; case maps:take(Field, ConnInfo0) of
_ -> {Value, NConnInfo} ->
{ClientInfo, ConnInfo} {ClientInfo0#{Field => Value}, NConnInfo};
end. _ ->
{ClientInfo0, ConnInfo0}
end
end,
{ClientInfo, ConnInfo},
Fields
).
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Handle incoming packet %% Handle incoming packet
@ -327,7 +339,7 @@ take_ws_cookie(ClientInfo, ConnInfo) ->
| {shutdown, Reason :: term(), channel()} | {shutdown, Reason :: term(), channel()}
| {shutdown, Reason :: term(), replies(), channel()}. | {shutdown, Reason :: term(), replies(), channel()}.
handle_in(?CONNECT_PACKET(), Channel = #channel{conn_state = ConnState}) when handle_in(?CONNECT_PACKET(), Channel = #channel{conn_state = ConnState}) when
ConnState =:= connected orelse ConnState =:= reauthenticating ?IS_CONNECTED_OR_REAUTHENTICATING(ConnState)
-> ->
handle_out(disconnect, ?RC_PROTOCOL_ERROR, Channel); handle_out(disconnect, ?RC_PROTOCOL_ERROR, Channel);
handle_in(?CONNECT_PACKET(), Channel = #channel{conn_state = connecting}) -> handle_in(?CONNECT_PACKET(), Channel = #channel{conn_state = connecting}) ->
@ -544,8 +556,10 @@ handle_in(
{error, ReasonCode} -> {error, ReasonCode} ->
handle_out(disconnect, ReasonCode, Channel) handle_out(disconnect, ReasonCode, Channel)
end; end;
handle_in(?PACKET(?PINGREQ), Channel) -> handle_in(?PACKET(?PINGREQ), Channel = #channel{keepalive = Keepalive}) ->
{ok, ?PACKET(?PINGRESP), Channel}; {ok, NKeepalive} = emqx_keepalive:check(Keepalive),
NChannel = Channel#channel{keepalive = NKeepalive},
{ok, ?PACKET(?PINGRESP), reset_timer(keepalive, NChannel)};
handle_in( handle_in(
?DISCONNECT_PACKET(ReasonCode, Properties), ?DISCONNECT_PACKET(ReasonCode, Properties),
Channel = #channel{conninfo = ConnInfo} Channel = #channel{conninfo = ConnInfo}
@ -555,29 +569,8 @@ handle_in(
process_disconnect(ReasonCode, Properties, NChannel); process_disconnect(ReasonCode, Properties, NChannel);
handle_in(?AUTH_PACKET(), Channel) -> handle_in(?AUTH_PACKET(), Channel) ->
handle_out(disconnect, ?RC_IMPLEMENTATION_SPECIFIC_ERROR, Channel); handle_out(disconnect, ?RC_IMPLEMENTATION_SPECIFIC_ERROR, Channel);
handle_in({frame_error, Reason}, Channel = #channel{conn_state = idle}) -> handle_in({frame_error, Reason}, Channel) ->
shutdown(shutdown_count(frame_error, Reason), Channel); handle_frame_error(Reason, Channel);
handle_in(
{frame_error, #{cause := frame_too_large} = R}, Channel = #channel{conn_state = connecting}
) ->
shutdown(
shutdown_count(frame_error, R), ?CONNACK_PACKET(?RC_PACKET_TOO_LARGE), Channel
);
handle_in({frame_error, Reason}, Channel = #channel{conn_state = connecting}) ->
shutdown(shutdown_count(frame_error, Reason), ?CONNACK_PACKET(?RC_MALFORMED_PACKET), Channel);
handle_in(
{frame_error, #{cause := frame_too_large}}, Channel = #channel{conn_state = ConnState}
) when
ConnState =:= connected orelse ConnState =:= reauthenticating
->
handle_out(disconnect, {?RC_PACKET_TOO_LARGE, frame_too_large}, Channel);
handle_in({frame_error, Reason}, Channel = #channel{conn_state = ConnState}) when
ConnState =:= connected orelse ConnState =:= reauthenticating
->
handle_out(disconnect, {?RC_MALFORMED_PACKET, Reason}, Channel);
handle_in({frame_error, Reason}, Channel = #channel{conn_state = disconnected}) ->
?SLOG(error, #{msg => "malformed_mqtt_message", reason => Reason}),
{ok, Channel};
handle_in(Packet, Channel) -> handle_in(Packet, Channel) ->
?SLOG(error, #{msg => "disconnecting_due_to_unexpected_message", packet => Packet}), ?SLOG(error, #{msg => "disconnecting_due_to_unexpected_message", packet => Packet}),
handle_out(disconnect, ?RC_PROTOCOL_ERROR, Channel). handle_out(disconnect, ?RC_PROTOCOL_ERROR, Channel).
@ -684,21 +677,28 @@ process_publish(Packet = ?PUBLISH_PACKET(QoS, Topic, PacketId), Channel) ->
end. end.
packet_to_message(Packet, #channel{ packet_to_message(Packet, #channel{
conninfo = #{proto_ver := ProtoVer}, conninfo = #{
clientinfo = #{ peername := PeerName,
protocol := Protocol, proto_ver := ProtoVer
clientid := ClientId, },
username := Username, clientinfo =
peerhost := PeerHost, #{
mountpoint := MountPoint protocol := Protocol,
} clientid := ClientId,
username := Username,
peerhost := PeerHost,
mountpoint := MountPoint
} = ClientInfo
}) -> }) ->
ClientAttrs = maps:get(client_attrs, ClientInfo, #{}),
emqx_mountpoint:mount( emqx_mountpoint:mount(
MountPoint, MountPoint,
emqx_packet:to_message( emqx_packet:to_message(
Packet, Packet,
ClientId, ClientId,
#{ #{
client_attrs => ClientAttrs,
peername => PeerName,
proto_ver => ProtoVer, proto_ver => ProtoVer,
protocol => Protocol, protocol => Protocol,
username => Username, username => Username,
@ -1002,6 +1002,68 @@ not_nacked({deliver, _Topic, Msg}) ->
true true
end. end.
%%--------------------------------------------------------------------
%% Handle Frame Error
%%--------------------------------------------------------------------
handle_frame_error(
Reason = #{cause := frame_too_large},
Channel = #channel{conn_state = ConnState, conninfo = ConnInfo}
) when
?IS_CONNECTED_OR_REAUTHENTICATING(ConnState)
->
ShutdownCount = shutdown_count(frame_error, Reason),
case proto_ver(Reason, ConnInfo) of
?MQTT_PROTO_V5 ->
handle_out(disconnect, {?RC_PACKET_TOO_LARGE, frame_too_large}, Channel);
_ ->
shutdown(ShutdownCount, Channel)
end;
%% Only send CONNACK with reason code `frame_too_large` for MQTT-v5.0 when connecting,
%% otherwise DONOT send any CONNACK or DISCONNECT packet.
handle_frame_error(
Reason,
Channel = #channel{conn_state = ConnState, conninfo = ConnInfo}
) when
is_map(Reason) andalso
(ConnState == idle orelse ConnState == connecting)
->
ShutdownCount = shutdown_count(frame_error, Reason),
ProtoVer = proto_ver(Reason, ConnInfo),
NChannel = Channel#channel{conninfo = ConnInfo#{proto_ver => ProtoVer}},
case ProtoVer of
?MQTT_PROTO_V5 ->
shutdown(ShutdownCount, ?CONNACK_PACKET(?RC_PACKET_TOO_LARGE), NChannel);
_ ->
shutdown(ShutdownCount, NChannel)
end;
handle_frame_error(
Reason,
Channel = #channel{conn_state = connecting}
) ->
shutdown(
shutdown_count(frame_error, Reason),
?CONNACK_PACKET(?RC_MALFORMED_PACKET),
Channel
);
handle_frame_error(
Reason,
Channel = #channel{conn_state = ConnState}
) when
?IS_CONNECTED_OR_REAUTHENTICATING(ConnState)
->
handle_out(
disconnect,
{?RC_MALFORMED_PACKET, Reason},
Channel
);
handle_frame_error(
Reason,
Channel = #channel{conn_state = disconnected}
) ->
?SLOG(error, #{msg => "malformed_mqtt_message", reason => Reason}),
{ok, Channel}.
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Handle outgoing packet %% Handle outgoing packet
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
@ -1222,11 +1284,12 @@ handle_call(
{keepalive, Interval}, {keepalive, Interval},
Channel = #channel{ Channel = #channel{
keepalive = KeepAlive, keepalive = KeepAlive,
conninfo = ConnInfo conninfo = ConnInfo,
clientinfo = #{zone := Zone}
} }
) -> ) ->
ClientId = info(clientid, Channel), ClientId = info(clientid, Channel),
NKeepalive = emqx_keepalive:update(timer:seconds(Interval), KeepAlive), NKeepalive = emqx_keepalive:update(Zone, Interval, KeepAlive),
NConnInfo = maps:put(keepalive, Interval, ConnInfo), NConnInfo = maps:put(keepalive, Interval, ConnInfo),
NChannel = Channel#channel{keepalive = NKeepalive, conninfo = NConnInfo}, NChannel = Channel#channel{keepalive = NKeepalive, conninfo = NConnInfo},
SockInfo = maps:get(sockinfo, emqx_cm:get_chan_info(ClientId), #{}), SockInfo = maps:get(sockinfo, emqx_cm:get_chan_info(ClientId), #{}),
@ -1269,7 +1332,7 @@ handle_info(
session = Session session = Session
} }
) when ) when
ConnState =:= connected orelse ConnState =:= reauthenticating ?IS_CONNECTED_OR_REAUTHENTICATING(ConnState)
-> ->
{Intent, Session1} = session_disconnect(ClientInfo, ConnInfo, Session), {Intent, Session1} = session_disconnect(ClientInfo, ConnInfo, Session),
Channel1 = ensure_disconnected(Reason, maybe_publish_will_msg(sock_closed, Channel)), Channel1 = ensure_disconnected(Reason, maybe_publish_will_msg(sock_closed, Channel)),
@ -1299,6 +1362,9 @@ handle_info({'DOWN', Ref, process, Pid, Reason}, Channel) ->
[] -> {ok, Channel}; [] -> {ok, Channel};
Msgs -> {ok, Msgs, Channel} Msgs -> {ok, Msgs, Channel}
end; end;
handle_info(?session_message(Message), #channel{session = Session} = Channel) ->
NSession = emqx_session:handle_info(Message, Session),
{ok, Channel#channel{session = NSession}};
handle_info(Info, Channel) -> handle_info(Info, Channel) ->
?SLOG(error, #{msg => "unexpected_info", info => Info}), ?SLOG(error, #{msg => "unexpected_info", info => Info}),
{ok, Channel}. {ok, Channel}.
@ -1326,22 +1392,22 @@ die_if_test_compiled() ->
| {shutdown, Reason :: term(), channel()}. | {shutdown, Reason :: term(), channel()}.
handle_timeout( handle_timeout(
_TRef, _TRef,
{keepalive, _StatVal}, keepalive,
Channel = #channel{keepalive = undefined} Channel = #channel{keepalive = undefined}
) -> ) ->
{ok, Channel}; {ok, Channel};
handle_timeout( handle_timeout(
_TRef, _TRef,
{keepalive, _StatVal}, keepalive,
Channel = #channel{conn_state = disconnected} Channel = #channel{conn_state = disconnected}
) -> ) ->
{ok, Channel}; {ok, Channel};
handle_timeout( handle_timeout(
_TRef, _TRef,
{keepalive, StatVal}, keepalive,
Channel = #channel{keepalive = Keepalive} Channel = #channel{keepalive = Keepalive}
) -> ) ->
case emqx_keepalive:check(StatVal, Keepalive) of case emqx_keepalive:check(Keepalive) of
{ok, NKeepalive} -> {ok, NKeepalive} ->
NChannel = Channel#channel{keepalive = NKeepalive}, NChannel = Channel#channel{keepalive = NKeepalive},
{ok, reset_timer(keepalive, NChannel)}; {ok, reset_timer(keepalive, NChannel)};
@ -1452,10 +1518,16 @@ reset_timer(Name, Time, Channel) ->
ensure_timer(Name, Time, clean_timer(Name, Channel)). ensure_timer(Name, Time, clean_timer(Name, Channel)).
clean_timer(Name, Channel = #channel{timers = Timers}) -> clean_timer(Name, Channel = #channel{timers = Timers}) ->
Channel#channel{timers = maps:remove(Name, Timers)}. case maps:take(Name, Timers) of
error ->
Channel;
{TRef, NTimers} ->
ok = emqx_utils:cancel_timer(TRef),
Channel#channel{timers = NTimers}
end.
interval(keepalive, #channel{keepalive = KeepAlive}) -> interval(keepalive, #channel{keepalive = KeepAlive}) ->
emqx_keepalive:info(interval, KeepAlive); emqx_keepalive:info(check_interval, KeepAlive);
interval(retry_delivery, #channel{session = Session}) -> interval(retry_delivery, #channel{session = Session}) ->
emqx_session:info(retry_interval, Session); emqx_session:info(retry_interval, Session);
interval(expire_awaiting_rel, #channel{session = Session}) -> interval(expire_awaiting_rel, #channel{session = Session}) ->
@ -1722,6 +1794,16 @@ count_flapping_event(_ConnPkt, #channel{clientinfo = ClientInfo}) ->
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Authenticate %% Authenticate
%% If peercert exists, add it as `cert_pem` credential field.
maybe_add_cert(Map, #channel{conninfo = ConnInfo}) ->
maybe_add_cert(Map, ConnInfo);
maybe_add_cert(Map, #{peercert := PeerCert}) when is_binary(PeerCert) ->
%% NOTE: it's raw binary at this point,
%% encoding to PEM (base64) is done lazy in emqx_auth_utils:render_var
Map#{cert_pem => PeerCert};
maybe_add_cert(Map, _) ->
Map.
authenticate( authenticate(
?CONNECT_PACKET( ?CONNECT_PACKET(
#mqtt_packet_connect{ #mqtt_packet_connect{
@ -1734,20 +1816,23 @@ authenticate(
auth_cache = AuthCache auth_cache = AuthCache
} = Channel } = Channel
) -> ) ->
%% Auth with CONNECT packet for MQTT v5
AuthData = emqx_mqtt_props:get('Authentication-Data', Properties, undefined), AuthData = emqx_mqtt_props:get('Authentication-Data', Properties, undefined),
do_authenticate( Credential0 =
ClientInfo#{ ClientInfo#{
auth_method => AuthMethod, auth_method => AuthMethod,
auth_data => AuthData, auth_data => AuthData,
auth_cache => AuthCache auth_cache => AuthCache
}, },
Channel Credential = maybe_add_cert(Credential0, Channel),
); do_authenticate(Credential, Channel);
authenticate( authenticate(
?CONNECT_PACKET(#mqtt_packet_connect{password = Password}), ?CONNECT_PACKET(#mqtt_packet_connect{password = Password}),
#channel{clientinfo = ClientInfo} = Channel #channel{clientinfo = ClientInfo} = Channel
) -> ) ->
do_authenticate(ClientInfo#{password => Password}, Channel); %% Auth with CONNECT packet for MQTT v3
Credential = maybe_add_cert(ClientInfo#{password => Password}, Channel),
do_authenticate(Credential, Channel);
authenticate( authenticate(
?AUTH_PACKET(_, #{'Authentication-Method' := AuthMethod} = Properties), ?AUTH_PACKET(_, #{'Authentication-Method' := AuthMethod} = Properties),
#channel{ #channel{
@ -1756,6 +1841,7 @@ authenticate(
auth_cache = AuthCache auth_cache = AuthCache
} = Channel } = Channel
) -> ) ->
%% Enhanced auth
case emqx_mqtt_props:get('Authentication-Method', ConnProps, undefined) of case emqx_mqtt_props:get('Authentication-Method', ConnProps, undefined) of
AuthMethod -> AuthMethod ->
AuthData = emqx_mqtt_props:get('Authentication-Data', Properties, undefined), AuthData = emqx_mqtt_props:get('Authentication-Data', Properties, undefined),
@ -2299,9 +2385,7 @@ ensure_keepalive_timer(0, Channel) ->
ensure_keepalive_timer(disabled, Channel) -> ensure_keepalive_timer(disabled, Channel) ->
Channel; Channel;
ensure_keepalive_timer(Interval, Channel = #channel{clientinfo = #{zone := Zone}}) -> ensure_keepalive_timer(Interval, Channel = #channel{clientinfo = #{zone := Zone}}) ->
Multiplier = get_mqtt_conf(Zone, keepalive_multiplier), Keepalive = emqx_keepalive:init(Zone, Interval),
RecvCnt = emqx_pd:get_counter(recv_pkt),
Keepalive = emqx_keepalive:init(RecvCnt, round(timer:seconds(Interval) * Multiplier)),
ensure_timer(keepalive, Channel#channel{keepalive = Keepalive}). ensure_timer(keepalive, Channel#channel{keepalive = Keepalive}).
clear_keepalive(Channel = #channel{timers = Timers}) -> clear_keepalive(Channel = #channel{timers = Timers}) ->
@ -2595,8 +2679,7 @@ save_alias(outbound, AliasId, Topic, TopicAliases = #{outbound := Aliases}) ->
NAliases = maps:put(Topic, AliasId, Aliases), NAliases = maps:put(Topic, AliasId, Aliases),
TopicAliases#{outbound => NAliases}. TopicAliases#{outbound => NAliases}.
-compile({inline, [reply/2, shutdown/2, shutdown/3, sp/1, flag/1]}). -compile({inline, [reply/2, shutdown/2, shutdown/3]}).
reply(Reply, Channel) -> reply(Reply, Channel) ->
{reply, Reply, Channel}. {reply, Reply, Channel}.
@ -2632,14 +2715,19 @@ disconnect_and_shutdown(
?IS_MQTT_V5 = ?IS_MQTT_V5 =
#channel{conn_state = ConnState} #channel{conn_state = ConnState}
) when ) when
ConnState =:= connected orelse ConnState =:= reauthenticating ?IS_CONNECTED_OR_REAUTHENTICATING(ConnState)
-> ->
NChannel = ensure_disconnected(Reason, Channel), NChannel = ensure_disconnected(Reason, Channel),
shutdown(Reason, Reply, ?DISCONNECT_PACKET(reason_code(Reason)), NChannel); shutdown(Reason, Reply, ?DISCONNECT_PACKET(reason_code(Reason)), NChannel);
%% mqtt v3/v4 sessions, mqtt v5 other conn_state sessions %% mqtt v3/v4 connected sessions
disconnect_and_shutdown(Reason, Reply, Channel) -> disconnect_and_shutdown(Reason, Reply, Channel = #channel{conn_state = ConnState}) when
?IS_CONNECTED_OR_REAUTHENTICATING(ConnState)
->
NChannel = ensure_disconnected(Reason, Channel), NChannel = ensure_disconnected(Reason, Channel),
shutdown(Reason, Reply, NChannel). shutdown(Reason, Reply, NChannel);
%% other conn_state sessions
disconnect_and_shutdown(Reason, Reply, Channel) ->
shutdown(Reason, Reply, Channel).
-compile({inline, [sp/1, flag/1]}). -compile({inline, [sp/1, flag/1]}).
sp(true) -> 1; sp(true) -> 1;
@ -2676,6 +2764,13 @@ is_durable_session(#channel{session = Session}) ->
false false
end. end.
proto_ver(#{proto_ver := ProtoVer}, _ConnInfo) ->
ProtoVer;
proto_ver(_Reason, #{proto_ver := ProtoVer}) ->
ProtoVer;
proto_ver(_, _) ->
?MQTT_PROTO_V4.
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% For CT tests %% For CT tests
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------

View File

@ -53,6 +53,7 @@ init([]) ->
RegistryKeeper = child_spec(emqx_cm_registry_keeper, 5000, worker), RegistryKeeper = child_spec(emqx_cm_registry_keeper, 5000, worker),
Manager = child_spec(emqx_cm, 5000, worker), Manager = child_spec(emqx_cm, 5000, worker),
DSSessionGCSup = child_spec(emqx_persistent_session_ds_sup, infinity, supervisor), DSSessionGCSup = child_spec(emqx_persistent_session_ds_sup, infinity, supervisor),
DSSessionBookkeeper = child_spec(emqx_persistent_session_bookkeeper, 5_000, worker),
Children = Children =
[ [
Banned, Banned,
@ -62,7 +63,8 @@ init([]) ->
Registry, Registry,
RegistryKeeper, RegistryKeeper,
Manager, Manager,
DSSessionGCSup DSSessionGCSup,
DSSessionBookkeeper
], ],
{ok, {SupFlags, Children}}. {ok, {SupFlags, Children}}.

View File

@ -118,6 +118,7 @@
config/0, config/0,
app_envs/0, app_envs/0,
update_opts/0, update_opts/0,
cluster_rpc_opts/0,
update_cmd/0, update_cmd/0,
update_args/0, update_args/0,
update_error/0, update_error/0,
@ -147,6 +148,7 @@
raw_config => emqx_config:raw_config(), raw_config => emqx_config:raw_config(),
post_config_update => #{module() => any()} post_config_update => #{module() => any()}
}. }.
-type cluster_rpc_opts() :: #{kind => ?KIND_INITIATE | ?KIND_REPLICATE}.
%% raw_config() is the config that is NOT parsed and translated by hocon schema %% raw_config() is the config that is NOT parsed and translated by hocon schema
-type raw_config() :: #{binary() => term()} | list() | undefined. -type raw_config() :: #{binary() => term()} | list() | undefined.
@ -497,15 +499,14 @@ fill_defaults(RawConf, Opts) ->
). ).
-spec fill_defaults(module(), raw_config(), hocon_tconf:opts()) -> map(). -spec fill_defaults(module(), raw_config(), hocon_tconf:opts()) -> map().
fill_defaults(_SchemaMod, RawConf = #{<<"durable_storage">> := _}, _) -> fill_defaults(SchemaMod, RawConf = #{<<"durable_storage">> := Ds}, Opts) ->
%% FIXME: kludge to prevent `emqx_config' module from filling in %% FIXME: kludge to prevent `emqx_config' module from filling in
%% the default values for backends and layouts. These records are %% the default values for backends and layouts. These records are
%% inside unions, and adding default values there will add %% inside unions, and adding default values there will add
%% incompatible fields. %% incompatible fields.
%% RawConf1 = maps:remove(<<"durable_storage">>, RawConf),
%% Note: this function is called for each individual conf root, so Conf = fill_defaults(SchemaMod, RawConf1, Opts),
%% this clause only affects this particular subtree. Conf#{<<"durable_storage">> => Ds};
RawConf;
fill_defaults(SchemaMod, RawConf, Opts0) -> fill_defaults(SchemaMod, RawConf, Opts0) ->
Opts = maps:merge(#{required => false, make_serializable => true}, Opts0), Opts = maps:merge(#{required => false, make_serializable => true}, Opts0),
hocon_tconf:check_plain( hocon_tconf:check_plain(

View File

@ -18,6 +18,7 @@
-module(emqx_config_handler). -module(emqx_config_handler).
-include("logger.hrl"). -include("logger.hrl").
-include("emqx.hrl").
-include("emqx_schema.hrl"). -include("emqx_schema.hrl").
-include_lib("hocon/include/hocon_types.hrl"). -include_lib("hocon/include/hocon_types.hrl").
@ -30,6 +31,7 @@
add_handler/2, add_handler/2,
remove_handler/1, remove_handler/1,
update_config/3, update_config/3,
update_config/4,
get_raw_cluster_override_conf/0, get_raw_cluster_override_conf/0,
info/0 info/0
]). ]).
@ -53,9 +55,13 @@
-optional_callbacks([ -optional_callbacks([
pre_config_update/3, pre_config_update/3,
pre_config_update/4,
propagated_pre_config_update/3, propagated_pre_config_update/3,
propagated_pre_config_update/4,
post_config_update/5, post_config_update/5,
propagated_post_config_update/5 post_config_update/6,
propagated_post_config_update/5,
propagated_post_config_update/6
]). ]).
-callback pre_config_update([atom()], emqx_config:update_request(), emqx_config:raw_config()) -> -callback pre_config_update([atom()], emqx_config:update_request(), emqx_config:raw_config()) ->
@ -83,6 +89,38 @@
) -> ) ->
ok | {ok, Result :: any()} | {error, Reason :: term()}. ok | {ok, Result :: any()} | {error, Reason :: term()}.
-callback pre_config_update(
[atom()], emqx_config:update_request(), emqx_config:raw_config(), emqx_config:cluster_rpc_opts()
) ->
ok | {ok, emqx_config:update_request()} | {error, term()}.
-callback propagated_pre_config_update(
[binary()],
emqx_config:update_request(),
emqx_config:raw_config(),
emqx_config:cluster_rpc_opts()
) ->
ok | {ok, emqx_config:update_request()} | {error, term()}.
-callback post_config_update(
[atom()],
emqx_config:update_request(),
emqx_config:config(),
emqx_config:config(),
emqx_config:app_envs(),
emqx_config:cluster_rpc_opts()
) ->
ok | {ok, Result :: any()} | {error, Reason :: term()}.
-callback propagated_post_config_update(
[atom()],
emqx_config:update_request(),
emqx_config:config(),
emqx_config:config(),
emqx_config:app_envs(),
emqx_config:cluster_rpc_opts()
) ->
ok | {ok, Result :: any()} | {error, Reason :: term()}.
-type state() :: #{handlers := any()}. -type state() :: #{handlers := any()}.
-type config_key_path() :: emqx_utils_maps:config_key_path(). -type config_key_path() :: emqx_utils_maps:config_key_path().
@ -92,12 +130,17 @@ start_link() ->
stop() -> stop() ->
gen_server:stop(?MODULE). gen_server:stop(?MODULE).
-spec update_config(module(), config_key_path(), emqx_config:update_args()) ->
{ok, emqx_config:update_result()} | {error, emqx_config:update_error()}.
update_config(SchemaModule, ConfKeyPath, UpdateArgs) -> update_config(SchemaModule, ConfKeyPath, UpdateArgs) ->
update_config(SchemaModule, ConfKeyPath, UpdateArgs, #{}).
-spec update_config(module(), config_key_path(), emqx_config:update_args(), map()) ->
{ok, emqx_config:update_result()} | {error, emqx_config:update_error()}.
update_config(SchemaModule, ConfKeyPath, UpdateArgs, ClusterOpts) ->
%% force convert the path to a list of atoms, as there maybe some wildcard names/ids in the path %% force convert the path to a list of atoms, as there maybe some wildcard names/ids in the path
AtomKeyPath = [atom(Key) || Key <- ConfKeyPath], AtomKeyPath = [atom(Key) || Key <- ConfKeyPath],
gen_server:call(?MODULE, {change_config, SchemaModule, AtomKeyPath, UpdateArgs}, infinity). gen_server:call(
?MODULE, {change_config, SchemaModule, AtomKeyPath, UpdateArgs, ClusterOpts}, infinity
).
-spec add_handler(config_key_path(), handler_name()) -> -spec add_handler(config_key_path(), handler_name()) ->
ok | {error, {conflict, list()}}. ok | {error, {conflict, list()}}.
@ -130,11 +173,11 @@ handle_call({add_handler, ConfKeyPath, HandlerName}, _From, State = #{handlers :
{error, _Reason} = Error -> {reply, Error, State} {error, _Reason} = Error -> {reply, Error, State}
end; end;
handle_call( handle_call(
{change_config, SchemaModule, ConfKeyPath, UpdateArgs}, {change_config, SchemaModule, ConfKeyPath, UpdateArgs, ClusterRpcOpts},
_From, _From,
#{handlers := Handlers} = State #{handlers := Handlers} = State
) -> ) ->
Result = handle_update_request(SchemaModule, ConfKeyPath, Handlers, UpdateArgs), Result = handle_update_request(SchemaModule, ConfKeyPath, Handlers, UpdateArgs, ClusterRpcOpts),
{reply, Result, State}; {reply, Result, State};
handle_call(get_raw_cluster_override_conf, _From, State) -> handle_call(get_raw_cluster_override_conf, _From, State) ->
Reply = emqx_config:read_override_conf(#{override_to => cluster}), Reply = emqx_config:read_override_conf(#{override_to => cluster}),
@ -203,9 +246,9 @@ filter_top_level_handlers(Handlers) ->
Handlers Handlers
). ).
handle_update_request(SchemaModule, ConfKeyPath, Handlers, UpdateArgs) -> handle_update_request(SchemaModule, ConfKeyPath, Handlers, UpdateArgs, ClusterRpcOpts) ->
try try
do_handle_update_request(SchemaModule, ConfKeyPath, Handlers, UpdateArgs) do_handle_update_request(SchemaModule, ConfKeyPath, Handlers, UpdateArgs, ClusterRpcOpts)
catch catch
throw:Reason -> throw:Reason ->
{error, Reason}; {error, Reason};
@ -217,13 +260,14 @@ handle_update_request(SchemaModule, ConfKeyPath, Handlers, UpdateArgs) ->
update_req => UpdateArgs, update_req => UpdateArgs,
module => SchemaModule, module => SchemaModule,
key_path => ConfKeyPath, key_path => ConfKeyPath,
cluster_rpc_opts => ClusterRpcOpts,
stacktrace => ST stacktrace => ST
}), }),
{error, {config_update_crashed, Reason}} {error, {config_update_crashed, Reason}}
end. end.
do_handle_update_request(SchemaModule, ConfKeyPath, Handlers, UpdateArgs) -> do_handle_update_request(SchemaModule, ConfKeyPath, Handlers, UpdateArgs, ClusterOpts) ->
case process_update_request(ConfKeyPath, Handlers, UpdateArgs) of case process_update_request(ConfKeyPath, Handlers, UpdateArgs, ClusterOpts) of
{ok, NewRawConf, OverrideConf, Opts} -> {ok, NewRawConf, OverrideConf, Opts} ->
check_and_save_configs( check_and_save_configs(
SchemaModule, SchemaModule,
@ -232,23 +276,24 @@ do_handle_update_request(SchemaModule, ConfKeyPath, Handlers, UpdateArgs) ->
NewRawConf, NewRawConf,
OverrideConf, OverrideConf,
UpdateArgs, UpdateArgs,
Opts Opts,
ClusterOpts
); );
{error, Result} -> {error, Result} ->
{error, Result} {error, Result}
end. end.
process_update_request([_], _Handlers, {remove, _Opts}) -> process_update_request([_], _Handlers, {remove, _Opts}, _ClusterRpcOpts) ->
{error, "remove_root_is_forbidden"}; {error, "remove_root_is_forbidden"};
process_update_request(ConfKeyPath, _Handlers, {remove, Opts}) -> process_update_request(ConfKeyPath, _Handlers, {remove, Opts}, _ClusterRpcOpts) ->
OldRawConf = emqx_config:get_root_raw(ConfKeyPath), OldRawConf = emqx_config:get_root_raw(ConfKeyPath),
BinKeyPath = bin_path(ConfKeyPath), BinKeyPath = bin_path(ConfKeyPath),
NewRawConf = emqx_utils_maps:deep_remove(BinKeyPath, OldRawConf), NewRawConf = emqx_utils_maps:deep_remove(BinKeyPath, OldRawConf),
OverrideConf = remove_from_override_config(BinKeyPath, Opts), OverrideConf = remove_from_override_config(BinKeyPath, Opts),
{ok, NewRawConf, OverrideConf, Opts}; {ok, NewRawConf, OverrideConf, Opts};
process_update_request(ConfKeyPath, Handlers, {{update, UpdateReq}, Opts}) -> process_update_request(ConfKeyPath, Handlers, {{update, UpdateReq}, Opts}, ClusterRpcOpts) ->
OldRawConf = emqx_config:get_root_raw(ConfKeyPath), OldRawConf = emqx_config:get_root_raw(ConfKeyPath),
case do_update_config(ConfKeyPath, Handlers, OldRawConf, UpdateReq) of case do_update_config(ConfKeyPath, Handlers, OldRawConf, UpdateReq, ClusterRpcOpts) of
{ok, NewRawConf} -> {ok, NewRawConf} ->
OverrideConf = merge_to_override_config(NewRawConf, Opts), OverrideConf = merge_to_override_config(NewRawConf, Opts),
{ok, NewRawConf, OverrideConf, Opts}; {ok, NewRawConf, OverrideConf, Opts};
@ -256,15 +301,16 @@ process_update_request(ConfKeyPath, Handlers, {{update, UpdateReq}, Opts}) ->
Error Error
end. end.
do_update_config(ConfKeyPath, Handlers, OldRawConf, UpdateReq) -> do_update_config(ConfKeyPath, Handlers, OldRawConf, UpdateReq, ClusterRpcOpts) ->
do_update_config(ConfKeyPath, Handlers, OldRawConf, UpdateReq, []). do_update_config(ConfKeyPath, Handlers, OldRawConf, UpdateReq, ClusterRpcOpts, []).
do_update_config([], Handlers, OldRawConf, UpdateReq, ConfKeyPath) -> do_update_config([], Handlers, OldRawConf, UpdateReq, ClusterRpcOpts, ConfKeyPath) ->
call_pre_config_update(#{ call_pre_config_update(#{
handlers => Handlers, handlers => Handlers,
old_raw_conf => OldRawConf, old_raw_conf => OldRawConf,
update_req => UpdateReq, update_req => UpdateReq,
conf_key_path => ConfKeyPath, conf_key_path => ConfKeyPath,
cluster_rpc_opts => ClusterRpcOpts,
callback => pre_config_update, callback => pre_config_update,
is_propagated => false is_propagated => false
}); });
@ -273,13 +319,18 @@ do_update_config(
Handlers, Handlers,
OldRawConf, OldRawConf,
UpdateReq, UpdateReq,
ClusterRpcOpts,
ConfKeyPath0 ConfKeyPath0
) -> ) ->
ConfKeyPath = ConfKeyPath0 ++ [ConfKey], ConfKeyPath = ConfKeyPath0 ++ [ConfKey],
ConfKeyBin = bin(ConfKey), ConfKeyBin = bin(ConfKey),
SubOldRawConf = get_sub_config(ConfKeyBin, OldRawConf), SubOldRawConf = get_sub_config(ConfKeyBin, OldRawConf),
SubHandlers = get_sub_handlers(ConfKey, Handlers), SubHandlers = get_sub_handlers(ConfKey, Handlers),
case do_update_config(SubConfKeyPath, SubHandlers, SubOldRawConf, UpdateReq, ConfKeyPath) of case
do_update_config(
SubConfKeyPath, SubHandlers, SubOldRawConf, UpdateReq, ClusterRpcOpts, ConfKeyPath
)
of
{ok, NewUpdateReq} -> {ok, NewUpdateReq} ->
merge_to_old_config(#{ConfKeyBin => NewUpdateReq}, OldRawConf); merge_to_old_config(#{ConfKeyBin => NewUpdateReq}, OldRawConf);
Error -> Error ->
@ -293,12 +344,18 @@ check_and_save_configs(
NewRawConf, NewRawConf,
OverrideConf, OverrideConf,
UpdateArgs, UpdateArgs,
Opts Opts,
ClusterOpts
) -> ) ->
Schema = schema(SchemaModule, ConfKeyPath), Schema = schema(SchemaModule, ConfKeyPath),
Kind = maps:get(kind, ClusterOpts, ?KIND_INITIATE),
{AppEnvs, NewConf} = emqx_config:check_config(Schema, NewRawConf), {AppEnvs, NewConf} = emqx_config:check_config(Schema, NewRawConf),
OldConf = emqx_config:get_root(ConfKeyPath), OldConf = emqx_config:get_root(ConfKeyPath),
case do_post_config_update(ConfKeyPath, Handlers, OldConf, NewConf, AppEnvs, UpdateArgs, #{}) of case
do_post_config_update(
ConfKeyPath, Handlers, OldConf, NewConf, AppEnvs, UpdateArgs, ClusterOpts, #{}
)
of
{ok, Result0} -> {ok, Result0} ->
post_update_ok( post_update_ok(
AppEnvs, AppEnvs,
@ -310,21 +367,24 @@ check_and_save_configs(
UpdateArgs, UpdateArgs,
Result0 Result0
); );
{error, {post_config_update, HandlerName, Reason}} -> {error, {post_config_update, HandlerName, Reason}} when Kind =/= ?KIND_INITIATE ->
HandlePostFailureFun = ?SLOG(critical, #{
fun() -> msg => "post_config_update_failed_but_save_the_config_anyway",
post_update_ok( handler => HandlerName,
AppEnvs, reason => Reason
NewConf, }),
NewRawConf, post_update_ok(
OverrideConf, AppEnvs,
Opts, NewConf,
ConfKeyPath, NewRawConf,
UpdateArgs, OverrideConf,
#{} Opts,
) ConfKeyPath,
end, UpdateArgs,
{error, {post_config_update, HandlerName, {Reason, HandlePostFailureFun}}} #{}
);
{error, _} = Error ->
Error
end. end.
post_update_ok(AppEnvs, NewConf, NewRawConf, OverrideConf, Opts, ConfKeyPath, UpdateArgs, Result0) -> post_update_ok(AppEnvs, NewConf, NewRawConf, OverrideConf, Opts, ConfKeyPath, UpdateArgs, Result0) ->
@ -332,7 +392,9 @@ post_update_ok(AppEnvs, NewConf, NewRawConf, OverrideConf, Opts, ConfKeyPath, Up
Result1 = return_change_result(ConfKeyPath, UpdateArgs), Result1 = return_change_result(ConfKeyPath, UpdateArgs),
{ok, Result1#{post_config_update => Result0}}. {ok, Result1#{post_config_update => Result0}}.
do_post_config_update(ConfKeyPath, Handlers, OldConf, NewConf, AppEnvs, UpdateArgs, Result) -> do_post_config_update(
ConfKeyPath, Handlers, OldConf, NewConf, AppEnvs, UpdateArgs, ClusterOpts, Result
) ->
do_post_config_update( do_post_config_update(
ConfKeyPath, ConfKeyPath,
Handlers, Handlers,
@ -340,6 +402,7 @@ do_post_config_update(ConfKeyPath, Handlers, OldConf, NewConf, AppEnvs, UpdateAr
NewConf, NewConf,
AppEnvs, AppEnvs,
UpdateArgs, UpdateArgs,
ClusterOpts,
Result, Result,
[] []
). ).
@ -352,6 +415,7 @@ do_post_config_update(
AppEnvs, AppEnvs,
UpdateArgs, UpdateArgs,
Result, Result,
ClusterOpts,
ConfKeyPath ConfKeyPath
) -> ) ->
call_post_config_update(#{ call_post_config_update(#{
@ -362,6 +426,7 @@ do_post_config_update(
update_req => up_req(UpdateArgs), update_req => up_req(UpdateArgs),
result => Result, result => Result,
conf_key_path => ConfKeyPath, conf_key_path => ConfKeyPath,
cluster_rpc_opts => ClusterOpts,
callback => post_config_update callback => post_config_update
}); });
do_post_config_update( do_post_config_update(
@ -371,6 +436,7 @@ do_post_config_update(
NewConf, NewConf,
AppEnvs, AppEnvs,
UpdateArgs, UpdateArgs,
ClusterOpts,
Result, Result,
ConfKeyPath0 ConfKeyPath0
) -> ) ->
@ -385,6 +451,7 @@ do_post_config_update(
SubNewConf, SubNewConf,
AppEnvs, AppEnvs,
UpdateArgs, UpdateArgs,
ClusterOpts,
Result, Result,
ConfKeyPath ConfKeyPath
). ).
@ -428,37 +495,41 @@ call_proper_pre_config_update(
#{ #{
handlers := #{?MOD := Module}, handlers := #{?MOD := Module},
callback := Callback, callback := Callback,
update_req := UpdateReq, update_req := UpdateReq
old_raw_conf := OldRawConf
} = Ctx } = Ctx
) -> ) ->
case erlang:function_exported(Module, Callback, 3) of Arity = get_function_arity(Module, Callback, [3, 4]),
true -> case apply_pre_config_update(Module, Callback, Arity, Ctx) of
case apply_pre_config_update(Module, Ctx) of {ok, NewUpdateReq} ->
{ok, NewUpdateReq} -> {ok, NewUpdateReq};
{ok, NewUpdateReq}; ok ->
ok -> {ok, UpdateReq};
{ok, UpdateReq}; {error, Reason} ->
{error, Reason} -> {error, {pre_config_update, Module, Reason}}
{error, {pre_config_update, Module, Reason}}
end;
false ->
merge_to_old_config(UpdateReq, OldRawConf)
end; end;
call_proper_pre_config_update( call_proper_pre_config_update(
#{update_req := UpdateReq} #{update_req := UpdateReq}
) -> ) ->
{ok, UpdateReq}. {ok, UpdateReq}.
apply_pre_config_update(Module, #{ apply_pre_config_update(Module, Callback, 3, #{
conf_key_path := ConfKeyPath,
update_req := UpdateReq,
old_raw_conf := OldRawConf
}) ->
Module:Callback(ConfKeyPath, UpdateReq, OldRawConf);
apply_pre_config_update(Module, Callback, 4, #{
conf_key_path := ConfKeyPath, conf_key_path := ConfKeyPath,
update_req := UpdateReq, update_req := UpdateReq,
old_raw_conf := OldRawConf, old_raw_conf := OldRawConf,
callback := Callback cluster_rpc_opts := ClusterRpcOpts
}) -> }) ->
Module:Callback( Module:Callback(ConfKeyPath, UpdateReq, OldRawConf, ClusterRpcOpts);
ConfKeyPath, UpdateReq, OldRawConf apply_pre_config_update(_Module, _Callback, false, #{
). update_req := UpdateReq,
old_raw_conf := OldRawConf
}) ->
merge_to_old_config(UpdateReq, OldRawConf).
propagate_pre_config_updates_to_subconf( propagate_pre_config_updates_to_subconf(
#{handlers := #{?WKEY := _}} = Ctx #{handlers := #{?WKEY := _}} = Ctx
@ -560,28 +631,23 @@ call_proper_post_config_update(
result := Result result := Result
} = Ctx } = Ctx
) -> ) ->
case erlang:function_exported(Module, Callback, 5) of Arity = get_function_arity(Module, Callback, [5, 6]),
true -> case apply_post_config_update(Module, Callback, Arity, Ctx) of
case apply_post_config_update(Module, Ctx) of ok -> {ok, Result};
ok -> {ok, Result}; {ok, Result1} -> {ok, Result#{Module => Result1}};
{ok, Result1} -> {ok, Result#{Module => Result1}}; {error, Reason} -> {error, {post_config_update, Module, Reason}}
{error, Reason} -> {error, {post_config_update, Module, Reason}}
end;
false ->
{ok, Result}
end; end;
call_proper_post_config_update( call_proper_post_config_update(
#{result := Result} = _Ctx #{result := Result} = _Ctx
) -> ) ->
{ok, Result}. {ok, Result}.
apply_post_config_update(Module, #{ apply_post_config_update(Module, Callback, 5, #{
conf_key_path := ConfKeyPath, conf_key_path := ConfKeyPath,
update_req := UpdateReq, update_req := UpdateReq,
new_conf := NewConf, new_conf := NewConf,
old_conf := OldConf, old_conf := OldConf,
app_envs := AppEnvs, app_envs := AppEnvs
callback := Callback
}) -> }) ->
Module:Callback( Module:Callback(
ConfKeyPath, ConfKeyPath,
@ -589,7 +655,25 @@ apply_post_config_update(Module, #{
NewConf, NewConf,
OldConf, OldConf,
AppEnvs AppEnvs
). );
apply_post_config_update(Module, Callback, 6, #{
conf_key_path := ConfKeyPath,
update_req := UpdateReq,
cluster_rpc_opts := ClusterRpcOpts,
new_conf := NewConf,
old_conf := OldConf,
app_envs := AppEnvs
}) ->
Module:Callback(
ConfKeyPath,
UpdateReq,
NewConf,
OldConf,
AppEnvs,
ClusterRpcOpts
);
apply_post_config_update(_Module, _Callback, false, _Ctx) ->
ok.
propagate_post_config_updates_to_subconf( propagate_post_config_updates_to_subconf(
#{handlers := #{?WKEY := _}} = Ctx #{handlers := #{?WKEY := _}} = Ctx
@ -768,7 +852,9 @@ assert_callback_function(Mod) ->
_ = apply(Mod, module_info, []), _ = apply(Mod, module_info, []),
case case
erlang:function_exported(Mod, pre_config_update, 3) orelse erlang:function_exported(Mod, pre_config_update, 3) orelse
erlang:function_exported(Mod, post_config_update, 5) erlang:function_exported(Mod, post_config_update, 5) orelse
erlang:function_exported(Mod, pre_config_update, 4) orelse
erlang:function_exported(Mod, post_config_update, 6)
of of
true -> ok; true -> ok;
false -> error(#{msg => "bad_emqx_config_handler_callback", module => Mod}) false -> error(#{msg => "bad_emqx_config_handler_callback", module => Mod})
@ -811,3 +897,13 @@ load_prev_handlers() ->
save_handlers(Handlers) -> save_handlers(Handlers) ->
application:set_env(emqx, ?MODULE, Handlers). application:set_env(emqx, ?MODULE, Handlers).
get_function_arity(_Module, _Callback, []) ->
false;
get_function_arity(Module, Callback, [Arity | Opts]) ->
%% ensure module is loaded
Module = Module:module_info(module),
case erlang:function_exported(Module, Callback, Arity) of
true -> Arity;
false -> get_function_arity(Module, Callback, Opts)
end.

View File

@ -158,31 +158,6 @@
-define(ENABLED(X), (X =/= undefined)). -define(ENABLED(X), (X =/= undefined)).
-define(ALARM_TCP_CONGEST(Channel),
list_to_binary(
io_lib:format(
"mqtt_conn/congested/~ts/~ts",
[
emqx_channel:info(clientid, Channel),
emqx_channel:info(username, Channel)
]
)
)
).
-define(ALARM_CONN_INFO_KEYS, [
socktype,
sockname,
peername,
clientid,
username,
proto_name,
proto_ver,
connected_at
]).
-define(ALARM_SOCK_STATS_KEYS, [send_pend, recv_cnt, recv_oct, send_cnt, send_oct]).
-define(ALARM_SOCK_OPTS_KEYS, [high_watermark, high_msgq_watermark, sndbuf, recbuf, buffer]).
-define(LIMITER_BYTES_IN, bytes). -define(LIMITER_BYTES_IN, bytes).
-define(LIMITER_MESSAGE_IN, messages). -define(LIMITER_MESSAGE_IN, messages).
@ -198,7 +173,9 @@
system_code_change/4 system_code_change/4
]} ]}
). ).
-dialyzer({no_missing_calls, [handle_msg/2]}).
-ifndef(BUILD_WITHOUT_QUIC).
-spec start_link -spec start_link
(esockd:transport(), esockd:socket(), emqx_channel:opts()) -> (esockd:transport(), esockd:socket(), emqx_channel:opts()) ->
{ok, pid()}; {ok, pid()};
@ -208,6 +185,9 @@
emqx_quic_connection:cb_state() emqx_quic_connection:cb_state()
) -> ) ->
{ok, pid()}. {ok, pid()}.
-else.
-spec start_link(esockd:transport(), esockd:socket(), emqx_channel:opts()) -> {ok, pid()}.
-endif.
start_link(Transport, Socket, Options) -> start_link(Transport, Socket, Options) ->
Args = [self(), Transport, Socket, Options], Args = [self(), Transport, Socket, Options],
@ -330,11 +310,13 @@ init_state(
{ok, Peername} = Transport:ensure_ok_or_exit(peername, [Socket]), {ok, Peername} = Transport:ensure_ok_or_exit(peername, [Socket]),
{ok, Sockname} = Transport:ensure_ok_or_exit(sockname, [Socket]), {ok, Sockname} = Transport:ensure_ok_or_exit(sockname, [Socket]),
Peercert = Transport:ensure_ok_or_exit(peercert, [Socket]), Peercert = Transport:ensure_ok_or_exit(peercert, [Socket]),
PeerSNI = Transport:ensure_ok_or_exit(peersni, [Socket]),
ConnInfo = #{ ConnInfo = #{
socktype => Transport:type(Socket), socktype => Transport:type(Socket),
peername => Peername, peername => Peername,
sockname => Sockname, sockname => Sockname,
peercert => Peercert, peercert => Peercert,
peersni => PeerSNI,
conn_mod => ?MODULE conn_mod => ?MODULE
}, },
@ -346,7 +328,7 @@ init_state(
max_size => emqx_config:get_zone_conf(Zone, [mqtt, max_packet_size]) max_size => emqx_config:get_zone_conf(Zone, [mqtt, max_packet_size])
}, },
ParseState = emqx_frame:initial_parse_state(FrameOpts), ParseState = emqx_frame:initial_parse_state(FrameOpts),
Serialize = emqx_frame:serialize_opts(), Serialize = emqx_frame:initial_serialize_opts(FrameOpts),
%% Init Channel %% Init Channel
Channel = emqx_channel:init(ConnInfo, Opts), Channel = emqx_channel:init(ConnInfo, Opts),
GcState = GcState =
@ -491,19 +473,17 @@ cancel_stats_timer(State) ->
process_msg([], State) -> process_msg([], State) ->
{ok, State}; {ok, State};
process_msg([Msg | More], State) -> process_msg([Msg | More], State) ->
try try handle_msg(Msg, State) of
case handle_msg(Msg, State) of ok ->
ok -> process_msg(More, State);
process_msg(More, State); {ok, NState} ->
{ok, NState} -> process_msg(More, NState);
process_msg(More, NState); {ok, Msgs, NState} ->
{ok, Msgs, NState} -> process_msg(append_msg(More, Msgs), NState);
process_msg(append_msg(More, Msgs), NState); {stop, Reason, NState} ->
{stop, Reason, NState} -> {stop, Reason, NState};
{stop, Reason, NState}; {stop, Reason} ->
{stop, Reason} -> {stop, Reason, State}
{stop, Reason, State}
end
catch catch
exit:normal -> exit:normal ->
{stop, normal, State}; {stop, normal, State};
@ -589,12 +569,10 @@ handle_msg({Closed, _Sock}, State) when
handle_msg({Passive, _Sock}, State) when handle_msg({Passive, _Sock}, State) when
Passive == tcp_passive; Passive == ssl_passive; Passive =:= quic_passive Passive == tcp_passive; Passive == ssl_passive; Passive =:= quic_passive
-> ->
%% In Stats
Pubs = emqx_pd:reset_counter(incoming_pubs), Pubs = emqx_pd:reset_counter(incoming_pubs),
Bytes = emqx_pd:reset_counter(incoming_bytes), Bytes = emqx_pd:reset_counter(incoming_bytes),
InStats = #{cnt => Pubs, oct => Bytes},
%% Run GC and Check OOM %% Run GC and Check OOM
NState1 = check_oom(run_gc(InStats, State)), NState1 = check_oom(Pubs, Bytes, run_gc(Pubs, Bytes, State)),
handle_info(activate_socket, NState1); handle_info(activate_socket, NState1);
handle_msg( handle_msg(
Deliver = {deliver, _Topic, _Msg}, Deliver = {deliver, _Topic, _Msg},
@ -603,17 +581,6 @@ handle_msg(
ActiveN = get_active_n(Type, Listener), ActiveN = get_active_n(Type, Listener),
Delivers = [Deliver | emqx_utils:drain_deliver(ActiveN)], Delivers = [Deliver | emqx_utils:drain_deliver(ActiveN)],
with_channel(handle_deliver, [Delivers], State); with_channel(handle_deliver, [Delivers], State);
%% Something sent
handle_msg({inet_reply, _Sock, ok}, State = #state{listener = {Type, Listener}}) ->
case emqx_pd:get_counter(outgoing_pubs) > get_active_n(Type, Listener) of
true ->
Pubs = emqx_pd:reset_counter(outgoing_pubs),
Bytes = emqx_pd:reset_counter(outgoing_bytes),
OutStats = #{cnt => Pubs, oct => Bytes},
{ok, check_oom(run_gc(OutStats, State))};
false ->
ok
end;
handle_msg({inet_reply, _Sock, {error, Reason}}, State) -> handle_msg({inet_reply, _Sock, {error, Reason}}, State) ->
handle_info({sock_error, Reason}, State); handle_info({sock_error, Reason}, State);
handle_msg({connack, ConnAck}, State) -> handle_msg({connack, ConnAck}, State) ->
@ -729,9 +696,9 @@ handle_call(_From, Req, State = #state{channel = Channel}) ->
shutdown(Reason, Reply, State#state{channel = NChannel}); shutdown(Reason, Reply, State#state{channel = NChannel});
{shutdown, Reason, Reply, OutPacket, NChannel} -> {shutdown, Reason, Reply, OutPacket, NChannel} ->
NState = State#state{channel = NChannel}, NState = State#state{channel = NChannel},
ok = handle_outgoing(OutPacket, NState), {ok, NState2} = handle_outgoing(OutPacket, NState),
NState2 = graceful_shutdown_transport(Reason, NState), NState3 = graceful_shutdown_transport(Reason, NState2),
shutdown(Reason, Reply, NState2) shutdown(Reason, Reply, NState3)
end. end.
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
@ -765,9 +732,7 @@ handle_timeout(
disconnected -> disconnected ->
{ok, State}; {ok, State};
_ -> _ ->
%% recv_pkt: valid MQTT message with_channel(handle_timeout, [TRef, keepalive], State)
RecvCnt = emqx_pd:get_counter(recv_pkt),
handle_timeout(TRef, {keepalive, RecvCnt}, State)
end; end;
handle_timeout(TRef, Msg, State) -> handle_timeout(TRef, Msg, State) ->
with_channel(handle_timeout, [TRef, Msg], State). with_channel(handle_timeout, [TRef, Msg], State).
@ -818,7 +783,8 @@ parse_incoming(Data, Packets, State = #state{parse_state = ParseState}) ->
input_bytes => Data, input_bytes => Data,
parsed_packets => Packets parsed_packets => Packets
}), }),
{[{frame_error, Reason} | Packets], State}; NState = enrich_state(Reason, State),
{[{frame_error, Reason} | Packets], NState};
error:Reason:Stacktrace -> error:Reason:Stacktrace ->
?LOG(error, #{ ?LOG(error, #{
at_state => emqx_frame:describe_state(ParseState), at_state => emqx_frame:describe_state(ParseState),
@ -854,8 +820,8 @@ with_channel(Fun, Args, State = #state{channel = Channel}) ->
shutdown(Reason, State#state{channel = NChannel}); shutdown(Reason, State#state{channel = NChannel});
{shutdown, Reason, Packet, NChannel} -> {shutdown, Reason, Packet, NChannel} ->
NState = State#state{channel = NChannel}, NState = State#state{channel = NChannel},
ok = handle_outgoing(Packet, NState), {ok, NState2} = handle_outgoing(Packet, NState),
shutdown(Reason, NState) shutdown(Reason, NState2)
end. end.
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
@ -909,20 +875,35 @@ serialize_and_inc_stats_fun(#state{serialize = Serialize}) ->
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Send data %% Send data
-spec send(iodata(), state()) -> ok. -spec send(iodata(), state()) -> {ok, state()}.
send(IoData, #state{transport = Transport, socket = Socket, channel = Channel}) -> send(IoData, #state{transport = Transport, socket = Socket} = State) ->
Oct = iolist_size(IoData), Oct = iolist_size(IoData),
ok = emqx_metrics:inc('bytes.sent', Oct), emqx_metrics:inc('bytes.sent', Oct),
inc_counter(outgoing_bytes, Oct), inc_counter(outgoing_bytes, Oct),
emqx_congestion:maybe_alarm_conn_congestion(Socket, Transport, Channel), case Transport:send(Socket, IoData) of
case Transport:async_send(Socket, IoData, []) of
ok -> ok ->
ok; %% NOTE: for Transport=emqx_quic_stream, it's actually an
%% async_send, sent/1 should technically be called when
%% {quic, send_complete, _Stream, true | false} is received,
%% but it is handled early for simplicity
sent(State);
Error = {error, _Reason} -> Error = {error, _Reason} ->
%% Send an inet_reply to postpone handling the error %% Defer error handling
%% @FIXME: why not just return error? %% so it's handled the same as tcp_closed or ssl_closed
self() ! {inet_reply, Socket, Error}, self() ! {inet_reply, Socket, Error},
ok {ok, State}
end.
%% Some bytes sent
sent(#state{listener = {Type, Listener}} = State) ->
%% Run GC and check OOM after certain amount of messages or bytes sent.
case emqx_pd:get_counter(outgoing_pubs) > get_active_n(Type, Listener) of
true ->
Pubs = emqx_pd:reset_counter(outgoing_pubs),
Bytes = emqx_pd:reset_counter(outgoing_bytes),
{ok, check_oom(Pubs, Bytes, run_gc(Pubs, Bytes, State))};
false ->
{ok, State}
end. end.
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
@ -1013,17 +994,23 @@ check_limiter(
Data, Data,
WhenOk, WhenOk,
Msgs, Msgs,
#state{limiter_timer = undefined, limiter = Limiter} = State #state{channel = Channel, limiter_timer = undefined, limiter = Limiter} = State
) -> ) ->
case emqx_limiter_container:check_list(Needs, Limiter) of case emqx_limiter_container:check_list(Needs, Limiter) of
{ok, Limiter2} -> {ok, Limiter2} ->
WhenOk(Data, Msgs, State#state{limiter = Limiter2}); WhenOk(Data, Msgs, State#state{limiter = Limiter2});
{pause, Time, Limiter2} -> {pause, Time, Limiter2} ->
?SLOG(debug, #{ ?SLOG_THROTTLE(
msg => "pause_time_due_to_rate_limit", warning,
needs => Needs, #{
time_in_ms => Time msg => socket_receive_paused_by_rate_limit,
}), paused_ms => Time
},
#{
tag => "RATE",
clientid => emqx_channel:info(clientid, Channel)
}
),
Retry = #retry{ Retry = #retry{
types = [Type || {_, Type} <- Needs], types = [Type || {_, Type} <- Needs],
@ -1057,7 +1044,7 @@ check_limiter(
%% try to perform a retry %% try to perform a retry
-spec retry_limiter(state()) -> _. -spec retry_limiter(state()) -> _.
retry_limiter(#state{limiter = Limiter} = State) -> retry_limiter(#state{channel = Channel, limiter = Limiter} = State) ->
#retry{types = Types, data = Data, next = Next} = #retry{types = Types, data = Data, next = Next} =
emqx_limiter_container:get_retry_context(Limiter), emqx_limiter_container:get_retry_context(Limiter),
case emqx_limiter_container:retry_list(Types, Limiter) of case emqx_limiter_container:retry_list(Types, Limiter) of
@ -1071,11 +1058,17 @@ retry_limiter(#state{limiter = Limiter} = State) ->
} }
); );
{pause, Time, Limiter2} -> {pause, Time, Limiter2} ->
?SLOG(debug, #{ ?SLOG_THROTTLE(
msg => "pause_time_due_to_rate_limit", warning,
types => Types, #{
time_in_ms => Time msg => socket_receive_paused_by_rate_limit,
}), paused_ms => Time
},
#{
tag => "RATE",
clientid => emqx_channel:info(clientid, Channel)
}
),
TRef = start_timer(Time, limit_timeout), TRef = start_timer(Time, limit_timeout),
@ -1088,25 +1081,36 @@ retry_limiter(#state{limiter = Limiter} = State) ->
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Run GC and Check OOM %% Run GC and Check OOM
run_gc(Stats, State = #state{gc_state = GcSt, zone = Zone}) -> run_gc(Pubs, Bytes, State = #state{gc_state = GcSt, zone = Zone}) ->
case case
?ENABLED(GcSt) andalso not emqx_olp:backoff_gc(Zone) andalso ?ENABLED(GcSt) andalso not emqx_olp:backoff_gc(Zone) andalso
emqx_gc:run(Stats, GcSt) emqx_gc:run(Pubs, Bytes, GcSt)
of of
false -> State; false -> State;
{_IsGC, GcSt1} -> State#state{gc_state = GcSt1} {_IsGC, GcSt1} -> State#state{gc_state = GcSt1}
end. end.
check_oom(State = #state{channel = Channel}) -> check_oom(Pubs, Bytes, State = #state{channel = Channel}) ->
ShutdownPolicy = emqx_config:get_zone_conf( ShutdownPolicy = emqx_config:get_zone_conf(
emqx_channel:info(zone, Channel), [force_shutdown] emqx_channel:info(zone, Channel), [force_shutdown]
), ),
?tp(debug, check_oom, #{policy => ShutdownPolicy}),
case emqx_utils:check_oom(ShutdownPolicy) of case emqx_utils:check_oom(ShutdownPolicy) of
{shutdown, Reason} -> {shutdown, Reason} ->
%% triggers terminate/2 callback immediately %% triggers terminate/2 callback immediately
?tp(warning, check_oom_shutdown, #{
policy => ShutdownPolicy,
incoming_pubs => Pubs,
incoming_bytes => Bytes,
shutdown => Reason
}),
erlang:exit({shutdown, Reason}); erlang:exit({shutdown, Reason});
_ -> Result ->
?tp(debug, check_oom_ok, #{
policy => ShutdownPolicy,
incoming_pubs => Pubs,
incoming_bytes => Bytes,
result => Result
}),
ok ok
end, end,
State. State.
@ -1224,6 +1228,12 @@ inc_counter(Key, Inc) ->
_ = emqx_pd:inc_counter(Key, Inc), _ = emqx_pd:inc_counter(Key, Inc),
ok. ok.
enrich_state(#{parse_state := NParseState}, State) ->
Serialize = emqx_frame:serialize_opts(NParseState),
State#state{parse_state = NParseState, serialize = Serialize};
enrich_state(_, State) ->
State.
set_tcp_keepalive({quic, _Listener}) -> set_tcp_keepalive({quic, _Listener}) ->
ok; ok;
set_tcp_keepalive({Type, Id}) -> set_tcp_keepalive({Type, Id}) ->

View File

@ -18,7 +18,7 @@
-module(emqx_ds_schema). -module(emqx_ds_schema).
%% API: %% API:
-export([schema/0, translate_builtin/1]). -export([schema/0, translate_builtin_raft/1, translate_builtin_local/1]).
%% Behavior callbacks: %% Behavior callbacks:
-export([fields/1, desc/1, namespace/0]). -export([fields/1, desc/1, namespace/0]).
@ -32,42 +32,51 @@
%% Type declarations %% Type declarations
%%================================================================================ %%================================================================================
-ifndef(EMQX_RELEASE_EDITION).
-define(EMQX_RELEASE_EDITION, ce).
-endif.
-if(?EMQX_RELEASE_EDITION == ee).
-define(DEFAULT_BACKEND, builtin_raft).
-define(BUILTIN_BACKENDS, [ref(builtin_raft), ref(builtin_local)]).
-else.
-define(DEFAULT_BACKEND, builtin_local).
-define(BUILTIN_BACKENDS, [ref(builtin_local)]).
-endif.
%%================================================================================ %%================================================================================
%% API %% API
%%================================================================================ %%================================================================================
translate_builtin( translate_builtin_raft(
Backend = #{ Backend = #{
backend := builtin, backend := builtin_raft,
n_shards := NShards, n_shards := NShards,
n_sites := NSites, n_sites := NSites,
replication_factor := ReplFactor, replication_factor := ReplFactor,
layout := Layout layout := Layout
} }
) -> ) ->
Storage =
case Layout of
#{
type := wildcard_optimized,
bits_per_topic_level := BitsPerTopicLevel,
epoch_bits := EpochBits,
topic_index_bytes := TIBytes
} ->
{emqx_ds_storage_bitfield_lts, #{
bits_per_topic_level => BitsPerTopicLevel,
topic_index_bytes => TIBytes,
epoch_bits => EpochBits
}};
#{type := reference} ->
{emqx_ds_storage_reference, #{}}
end,
#{ #{
backend => builtin, backend => builtin_raft,
n_shards => NShards, n_shards => NShards,
n_sites => NSites, n_sites => NSites,
replication_factor => ReplFactor, replication_factor => ReplFactor,
replication_options => maps:get(replication_options, Backend, #{}), replication_options => maps:get(replication_options, Backend, #{}),
storage => Storage storage => translate_layout(Layout)
}.
translate_builtin_local(
#{
backend := builtin_local,
n_shards := NShards,
layout := Layout
}
) ->
#{
backend => builtin_local,
n_shards => NShards,
storage => translate_layout(Layout)
}. }.
%%================================================================================ %%================================================================================
@ -83,24 +92,24 @@ schema() ->
ds_schema(#{ ds_schema(#{
default => default =>
#{ #{
<<"backend">> => builtin <<"backend">> => ?DEFAULT_BACKEND
}, },
importance => ?IMPORTANCE_MEDIUM, importance => ?IMPORTANCE_MEDIUM,
desc => ?DESC(messages) desc => ?DESC(messages)
})} })}
]. ].
fields(builtin) -> fields(builtin_local) ->
%% Schema for the builtin backend: %% Schema for the builtin_raft backend:
[ [
{backend, {backend,
sc( sc(
builtin, builtin_local,
#{ #{
'readOnly' => true, 'readOnly' => true,
default => builtin, default => builtin_local,
importance => ?IMPORTANCE_MEDIUM, importance => ?IMPORTANCE_MEDIUM,
desc => ?DESC(builtin_backend) desc => ?DESC(backend_type)
} }
)}, )},
{'_config_handler', {'_config_handler',
@ -108,27 +117,32 @@ fields(builtin) ->
{module(), atom()}, {module(), atom()},
#{ #{
'readOnly' => true, 'readOnly' => true,
default => {?MODULE, translate_builtin}, default => {?MODULE, translate_builtin_local},
importance => ?IMPORTANCE_HIDDEN importance => ?IMPORTANCE_HIDDEN
} }
)}, )}
{data_dir, | common_builtin_fields()
];
fields(builtin_raft) ->
%% Schema for the builtin_raft backend:
[
{backend,
sc( sc(
string(), builtin_raft,
#{ #{
mapping => "emqx_durable_storage.db_data_dir", 'readOnly' => true,
required => false, default => builtin_raft,
importance => ?IMPORTANCE_MEDIUM, importance => ?IMPORTANCE_MEDIUM,
desc => ?DESC(builtin_data_dir) desc => ?DESC(backend_type)
} }
)}, )},
{n_shards, {'_config_handler',
sc( sc(
pos_integer(), {module(), atom()},
#{ #{
default => 16, 'readOnly' => true,
importance => ?IMPORTANCE_MEDIUM, default => {?MODULE, translate_builtin_raft},
desc => ?DESC(builtin_n_shards) importance => ?IMPORTANCE_HIDDEN
} }
)}, )},
%% TODO: Deprecate once cluster management and rebalancing is implemented. %% TODO: Deprecate once cluster management and rebalancing is implemented.
@ -157,29 +171,10 @@ fields(builtin) ->
default => #{}, default => #{},
importance => ?IMPORTANCE_HIDDEN importance => ?IMPORTANCE_HIDDEN
} }
)},
{local_write_buffer,
sc(
ref(builtin_local_write_buffer),
#{
importance => ?IMPORTANCE_HIDDEN,
desc => ?DESC(builtin_local_write_buffer)
}
)},
{layout,
sc(
hoconsc:union(builtin_layouts()),
#{
desc => ?DESC(builtin_layout),
importance => ?IMPORTANCE_MEDIUM,
default =>
#{
<<"type">> => wildcard_optimized
}
}
)} )}
| common_builtin_fields()
]; ];
fields(builtin_local_write_buffer) -> fields(builtin_write_buffer) ->
[ [
{max_items, {max_items,
sc( sc(
@ -188,7 +183,7 @@ fields(builtin_local_write_buffer) ->
default => 1000, default => 1000,
mapping => "emqx_durable_storage.egress_batch_size", mapping => "emqx_durable_storage.egress_batch_size",
importance => ?IMPORTANCE_HIDDEN, importance => ?IMPORTANCE_HIDDEN,
desc => ?DESC(builtin_local_write_buffer_max_items) desc => ?DESC(builtin_write_buffer_max_items)
} }
)}, )},
{flush_interval, {flush_interval,
@ -198,7 +193,7 @@ fields(builtin_local_write_buffer) ->
default => 100, default => 100,
mapping => "emqx_durable_storage.egress_flush_interval", mapping => "emqx_durable_storage.egress_flush_interval",
importance => ?IMPORTANCE_HIDDEN, importance => ?IMPORTANCE_HIDDEN,
desc => ?DESC(builtin_local_write_buffer_flush_interval) desc => ?DESC(builtin_write_buffer_flush_interval)
} }
)} )}
]; ];
@ -239,6 +234,42 @@ fields(layout_builtin_wildcard_optimized) ->
} }
)} )}
]; ];
fields(layout_builtin_wildcard_optimized_v2) ->
[
{type,
sc(
wildcard_optimized_v2,
#{
'readOnly' => true,
default => wildcard_optimized_v2,
desc => ?DESC(layout_builtin_wildcard_optimized_type)
}
)},
{bytes_per_topic_level,
sc(
range(1, 16),
#{
default => 8,
importance => ?IMPORTANCE_HIDDEN
}
)},
{topic_index_bytes,
sc(
pos_integer(),
#{
default => 8,
importance => ?IMPORTANCE_HIDDEN
}
)},
{serialization_schema,
sc(
emqx_ds_msg_serializer:schema(),
#{
default => v1,
importance => ?IMPORTANCE_HIDDEN
}
)}
];
fields(layout_builtin_reference) -> fields(layout_builtin_reference) ->
[ [
{type, {type,
@ -246,17 +277,68 @@ fields(layout_builtin_reference) ->
reference, reference,
#{ #{
'readOnly' => true, 'readOnly' => true,
importance => ?IMPORTANCE_HIDDEN importance => ?IMPORTANCE_LOW,
default => reference,
desc => ?DESC(layout_builtin_reference_type)
} }
)} )}
]. ].
desc(builtin) -> common_builtin_fields() ->
?DESC(builtin); [
desc(builtin_local_write_buffer) -> {data_dir,
?DESC(builtin_local_write_buffer); sc(
string(),
#{
mapping => "emqx_durable_storage.db_data_dir",
required => false,
importance => ?IMPORTANCE_MEDIUM,
desc => ?DESC(builtin_data_dir)
}
)},
{n_shards,
sc(
pos_integer(),
#{
default => 16,
importance => ?IMPORTANCE_MEDIUM,
desc => ?DESC(builtin_n_shards)
}
)},
{local_write_buffer,
sc(
ref(builtin_write_buffer),
#{
importance => ?IMPORTANCE_HIDDEN,
desc => ?DESC(builtin_write_buffer)
}
)},
{layout,
sc(
hoconsc:union(builtin_layouts()),
#{
desc => ?DESC(builtin_layout),
importance => ?IMPORTANCE_MEDIUM,
default =>
#{
<<"type">> => wildcard_optimized_v2
}
}
)}
].
desc(builtin_raft) ->
?DESC(builtin_raft);
desc(builtin_local) ->
?DESC(builtin_local);
desc(builtin_write_buffer) ->
?DESC(builtin_write_buffer);
desc(layout_builtin_wildcard_optimized) -> desc(layout_builtin_wildcard_optimized) ->
?DESC(layout_builtin_wildcard_optimized); ?DESC(layout_builtin_wildcard_optimized);
desc(layout_builtin_wildcard_optimized_v2) ->
?DESC(layout_builtin_wildcard_optimized);
desc(layout_builtin_reference) ->
?DESC(layout_builtin_reference);
desc(_) -> desc(_) ->
undefined. undefined.
@ -264,26 +346,53 @@ desc(_) ->
%% Internal functions %% Internal functions
%%================================================================================ %%================================================================================
translate_layout(
#{
type := wildcard_optimized_v2,
bytes_per_topic_level := BytesPerTopicLevel,
topic_index_bytes := TopicIndexBytes,
serialization_schema := SSchema
}
) ->
{emqx_ds_storage_skipstream_lts, #{
wildcard_hash_bytes => BytesPerTopicLevel,
topic_index_bytes => TopicIndexBytes,
serialization_schema => SSchema
}};
translate_layout(
#{
type := wildcard_optimized,
bits_per_topic_level := BitsPerTopicLevel,
epoch_bits := EpochBits,
topic_index_bytes := TIBytes
}
) ->
{emqx_ds_storage_bitfield_lts, #{
bits_per_topic_level => BitsPerTopicLevel,
topic_index_bytes => TIBytes,
epoch_bits => EpochBits
}};
translate_layout(#{type := reference}) ->
{emqx_ds_storage_reference, #{}}.
ds_schema(Options) -> ds_schema(Options) ->
sc( sc(
hoconsc:union([ hoconsc:union(
ref(builtin) ?BUILTIN_BACKENDS ++ emqx_schema_hooks:injection_point('durable_storage.backends', [])
| emqx_schema_hooks:injection_point('durable_storage.backends', []) ),
]),
Options Options
). ).
-ifndef(TEST).
builtin_layouts() ->
[ref(layout_builtin_wildcard_optimized)].
-else.
builtin_layouts() -> builtin_layouts() ->
%% Reference layout stores everything in one stream, so it's not %% Reference layout stores everything in one stream, so it's not
%% suitable for production use. However, it's very simple and %% suitable for production use. However, it's very simple and
%% produces a very predictabale replay order, which can be useful %% produces a very predictabale replay order, which can be useful
%% for testing and debugging: %% for testing and debugging:
[ref(layout_builtin_wildcard_optimized), ref(layout_builtin_reference)]. [
-endif. ref(layout_builtin_wildcard_optimized_v2),
ref(layout_builtin_wildcard_optimized),
ref(layout_builtin_reference)
].
sc(Type, Meta) -> hoconsc:mk(Type, Meta). sc(Type, Meta) -> hoconsc:mk(Type, Meta).

View File

@ -117,6 +117,13 @@ try_subscribe(ClientId, Topic) ->
write write
), ),
allow; allow;
[#exclusive_subscription{clientid = ClientId, topic = Topic}] ->
%% Fixed the issue-13476
%% In this feature, the user must manually call `unsubscribe` to release the lock,
%% but sometimes the node may go down for some reason,
%% then the client will reconnect to this node and resubscribe.
%% We need to allow resubscription, otherwise the lock will never be released.
allow;
[_] -> [_] ->
deny deny
end. end.

View File

@ -0,0 +1,148 @@
%%--------------------------------------------------------------------
%% Copyright (c) 2024 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_external_broker).
-callback forward(emqx_types:delivery()) ->
emqx_types:publish_result().
-callback add_route(emqx_types:topic()) -> ok.
-callback delete_route(emqx_types:topic()) -> ok.
-callback add_shared_route(emqx_types:topic(), emqx_types:group()) -> ok.
-callback delete_shared_route(emqx_types:topic(), emqx_types:group()) -> ok.
-callback add_persistent_route(emqx_types:topic(), emqx_persistent_session_ds:id()) -> ok.
-callback delete_persistent_route(emqx_types:topic(), emqx_persistent_session_ds:id()) -> ok.
-type dest() :: term().
-export([
%% Registration
provider/0,
register_provider/1,
unregister_provider/1,
%% Forwarding
forward/1,
%% Routing updates
add_route/1,
delete_route/1,
add_shared_route/2,
delete_shared_route/2,
add_persistent_route/2,
delete_persistent_route/2,
add_persistent_shared_route/3,
delete_persistent_shared_route/3
]).
-export_type([dest/0]).
-include("logger.hrl").
-define(PROVIDER, {?MODULE, external_broker}).
-define(safe_with_provider(IfRegistered, IfNotRegistered),
case persistent_term:get(?PROVIDER, undefined) of
undefined ->
IfNotRegistered;
Provider ->
try
Provider:IfRegistered
catch
Err:Reason:St ->
?SLOG_THROTTLE(error, #{
msg => external_broker_crashed,
provider => Provider,
callback => ?FUNCTION_NAME,
stacktrace => St,
error => Err,
reason => Reason
}),
{error, Reason}
end
end
).
%% TODO: provider API copied from emqx_external_traces,
%% but it can be moved to a common module.
%%--------------------------------------------------------------------
%% Provider API
%%--------------------------------------------------------------------
-spec register_provider(module()) -> ok | {error, term()}.
register_provider(Module) when is_atom(Module) ->
case is_valid_provider(Module) of
true ->
persistent_term:put(?PROVIDER, Module);
false ->
{error, invalid_provider}
end.
-spec unregister_provider(module()) -> ok | {error, term()}.
unregister_provider(Module) ->
case persistent_term:get(?PROVIDER, undefined) of
Module ->
persistent_term:erase(?PROVIDER),
ok;
_ ->
{error, not_registered}
end.
-spec provider() -> module() | undefined.
provider() ->
persistent_term:get(?PROVIDER, undefined).
%%--------------------------------------------------------------------
%% Broker API
%%--------------------------------------------------------------------
forward(Delivery) ->
?safe_with_provider(?FUNCTION_NAME(Delivery), []).
add_route(Topic) ->
?safe_with_provider(?FUNCTION_NAME(Topic), ok).
delete_route(Topic) ->
?safe_with_provider(?FUNCTION_NAME(Topic), ok).
add_shared_route(Topic, Group) ->
?safe_with_provider(?FUNCTION_NAME(Topic, Group), ok).
delete_shared_route(Topic, Group) ->
?safe_with_provider(?FUNCTION_NAME(Topic, Group), ok).
add_persistent_route(Topic, ID) ->
?safe_with_provider(?FUNCTION_NAME(Topic, ID), ok).
delete_persistent_route(Topic, ID) ->
?safe_with_provider(?FUNCTION_NAME(Topic, ID), ok).
add_persistent_shared_route(Topic, Group, ID) ->
?safe_with_provider(?FUNCTION_NAME(Topic, Group, ID), ok).
delete_persistent_shared_route(Topic, Group, ID) ->
?safe_with_provider(?FUNCTION_NAME(Topic, Group, ID), ok).
%%--------------------------------------------------------------------
%% Internal functions
%%--------------------------------------------------------------------
is_valid_provider(Module) ->
lists:all(
fun({F, A}) -> erlang:function_exported(Module, F, A) end,
?MODULE:behaviour_info(callbacks)
).

View File

@ -29,11 +29,12 @@
parse/2, parse/2,
serialize_fun/0, serialize_fun/0,
serialize_fun/1, serialize_fun/1,
serialize_opts/0, initial_serialize_opts/1,
serialize_opts/1, serialize_opts/1,
serialize_pkt/2, serialize_pkt/2,
serialize/1, serialize/1,
serialize/2 serialize/2,
serialize/3
]). ]).
-export([describe_state/1]). -export([describe_state/1]).
@ -84,7 +85,7 @@
-define(MULTIPLIER_MAX, 16#200000). -define(MULTIPLIER_MAX, 16#200000).
-dialyzer({no_match, [serialize_utf8_string/2]}). -dialyzer({no_match, [serialize_utf8_string/3]}).
%% @doc Describe state for logging. %% @doc Describe state for logging.
describe_state(?NONE(_Opts)) -> describe_state(?NONE(_Opts)) ->
@ -266,47 +267,76 @@ packet(Header, Variable) ->
packet(Header, Variable, Payload) -> packet(Header, Variable, Payload) ->
#mqtt_packet{header = Header, variable = Variable, payload = Payload}. #mqtt_packet{header = Header, variable = Variable, payload = Payload}.
parse_connect(FrameBin, StrictMode) -> parse_connect(FrameBin, Options = #{strict_mode := StrictMode}) ->
{ProtoName, Rest} = parse_utf8_string_with_cause(FrameBin, StrictMode, invalid_proto_name), {ProtoName, Rest0} = parse_utf8_string_with_cause(FrameBin, StrictMode, invalid_proto_name),
case ProtoName of %% No need to parse and check proto_ver if proto_name is invalid, check it first
<<"MQTT">> -> %% And the matching check of `proto_name` and `proto_ver` fields will be done in `emqx_packet:check_proto_ver/2`
ok; _ = validate_proto_name(ProtoName),
<<"MQIsdp">> -> {IsBridge, ProtoVer, Rest2} = parse_connect_proto_ver(Rest0),
ok; NOptions = Options#{version => ProtoVer},
_ -> try
%% from spec: the server MAY send disconnect with reason code 0x84 do_parse_connect(ProtoName, IsBridge, ProtoVer, Rest2, StrictMode)
%% we chose to close socket because the client is likely not talking MQTT anyway catch
?PARSE_ERR(#{ throw:{?FRAME_PARSE_ERROR, ReasonM} when is_map(ReasonM) ->
cause => invalid_proto_name, ?PARSE_ERR(
expected => <<"'MQTT' or 'MQIsdp'">>, ReasonM#{
received => ProtoName proto_ver => ProtoVer,
}) proto_name => ProtoName,
end, parse_state => ?NONE(NOptions)
parse_connect2(ProtoName, Rest, StrictMode). }
);
throw:{?FRAME_PARSE_ERROR, Reason} ->
?PARSE_ERR(
#{
cause => Reason,
proto_ver => ProtoVer,
proto_name => ProtoName,
parse_state => ?NONE(NOptions)
}
)
end.
% Note: return malformed if reserved flag is not 0. do_parse_connect(
parse_connect2(
ProtoName, ProtoName,
<<BridgeTag:4, ProtoVer:4, UsernameFlag:1, PasswordFlag:1, WillRetain:1, WillQoS:2, WillFlag:1, IsBridge,
CleanStart:1, Reserved:1, KeepAlive:16/big, Rest2/binary>>, ProtoVer,
<<
UsernameFlagB:1,
PasswordFlagB:1,
WillRetainB:1,
WillQoS:2,
WillFlagB:1,
CleanStart:1,
Reserved:1,
KeepAlive:16/big,
Rest/binary
>>,
StrictMode StrictMode
) -> ) ->
case Reserved of _ = validate_connect_reserved(Reserved),
0 -> ok; _ = validate_connect_will(
1 -> ?PARSE_ERR(reserved_connect_flag) WillFlag = bool(WillFlagB),
end, WillRetain = bool(WillRetainB),
{Properties, Rest3} = parse_properties(Rest2, ProtoVer, StrictMode), WillQoS
),
_ = validate_connect_password_flag(
StrictMode,
ProtoVer,
UsernameFlag = bool(UsernameFlagB),
PasswordFlag = bool(PasswordFlagB)
),
{Properties, Rest3} = parse_properties(Rest, ProtoVer, StrictMode),
{ClientId, Rest4} = parse_utf8_string_with_cause(Rest3, StrictMode, invalid_clientid), {ClientId, Rest4} = parse_utf8_string_with_cause(Rest3, StrictMode, invalid_clientid),
ConnPacket = #mqtt_packet_connect{ ConnPacket = #mqtt_packet_connect{
proto_name = ProtoName, proto_name = ProtoName,
proto_ver = ProtoVer, proto_ver = ProtoVer,
%% For bridge mode, non-standard implementation %% For bridge mode, non-standard implementation
%% Invented by mosquitto, named 'try_private': https://mosquitto.org/man/mosquitto-conf-5.html %% Invented by mosquitto, named 'try_private': https://mosquitto.org/man/mosquitto-conf-5.html
is_bridge = (BridgeTag =:= 8), is_bridge = IsBridge,
clean_start = bool(CleanStart), clean_start = bool(CleanStart),
will_flag = bool(WillFlag), will_flag = WillFlag,
will_qos = WillQoS, will_qos = WillQoS,
will_retain = bool(WillRetain), will_retain = WillRetain,
keepalive = KeepAlive, keepalive = KeepAlive,
properties = Properties, properties = Properties,
clientid = ClientId clientid = ClientId
@ -317,14 +347,14 @@ parse_connect2(
fun(Bin) -> fun(Bin) ->
parse_utf8_string_with_cause(Bin, StrictMode, invalid_username) parse_utf8_string_with_cause(Bin, StrictMode, invalid_username)
end, end,
bool(UsernameFlag) UsernameFlag
), ),
{Password, Rest7} = parse_optional( {Password, Rest7} = parse_optional(
Rest6, Rest6,
fun(Bin) -> fun(Bin) ->
parse_utf8_string_with_cause(Bin, StrictMode, invalid_password) parse_utf8_string_with_cause(Bin, StrictMode, invalid_password)
end, end,
bool(PasswordFlag) PasswordFlag
), ),
case Rest7 of case Rest7 of
<<>> -> <<>> ->
@ -335,16 +365,16 @@ parse_connect2(
unexpected_trailing_bytes => size(Rest7) unexpected_trailing_bytes => size(Rest7)
}) })
end; end;
parse_connect2(_ProtoName, Bin, _StrictMode) -> do_parse_connect(_ProtoName, _IsBridge, _ProtoVer, Bin, _StrictMode) ->
%% sent less than 32 bytes %% sent less than 24 bytes
?PARSE_ERR(#{cause => malformed_connect, header_bytes => Bin}). ?PARSE_ERR(#{cause => malformed_connect, header_bytes => Bin}).
parse_packet( parse_packet(
#mqtt_packet_header{type = ?CONNECT}, #mqtt_packet_header{type = ?CONNECT},
FrameBin, FrameBin,
#{strict_mode := StrictMode} Options
) -> ) ->
parse_connect(FrameBin, StrictMode); parse_connect(FrameBin, Options);
parse_packet( parse_packet(
#mqtt_packet_header{type = ?CONNACK}, #mqtt_packet_header{type = ?CONNACK},
<<AckFlags:8, ReasonCode:8, Rest/binary>>, <<AckFlags:8, ReasonCode:8, Rest/binary>>,
@ -508,6 +538,12 @@ parse_packet_id(<<PacketId:16/big, Rest/binary>>) ->
parse_packet_id(_) -> parse_packet_id(_) ->
?PARSE_ERR(invalid_packet_id). ?PARSE_ERR(invalid_packet_id).
parse_connect_proto_ver(<<BridgeTag:4, ProtoVer:4, Rest/binary>>) ->
{_IsBridge = (BridgeTag =:= 8), ProtoVer, Rest};
parse_connect_proto_ver(Bin) ->
%% sent less than 1 bytes or empty
?PARSE_ERR(#{cause => malformed_connect, header_bytes => Bin}).
parse_properties(Bin, Ver, _StrictMode) when Ver =/= ?MQTT_PROTO_V5 -> parse_properties(Bin, Ver, _StrictMode) when Ver =/= ?MQTT_PROTO_V5 ->
{#{}, Bin}; {#{}, Bin};
%% TODO: version mess? %% TODO: version mess?
@ -718,43 +754,53 @@ serialize_fun() -> serialize_fun(?DEFAULT_OPTIONS).
serialize_fun(#mqtt_packet_connect{proto_ver = ProtoVer, properties = ConnProps}) -> serialize_fun(#mqtt_packet_connect{proto_ver = ProtoVer, properties = ConnProps}) ->
MaxSize = get_property('Maximum-Packet-Size', ConnProps, ?MAX_PACKET_SIZE), MaxSize = get_property('Maximum-Packet-Size', ConnProps, ?MAX_PACKET_SIZE),
serialize_fun(#{version => ProtoVer, max_size => MaxSize}); serialize_fun(#{version => ProtoVer, max_size => MaxSize, strict_mode => false});
serialize_fun(#{version := Ver, max_size := MaxSize}) -> serialize_fun(#{version := Ver, max_size := MaxSize, strict_mode := StrictMode}) ->
fun(Packet) -> fun(Packet) ->
IoData = serialize(Packet, Ver), IoData = serialize(Packet, Ver, StrictMode),
case is_too_large(IoData, MaxSize) of case is_too_large(IoData, MaxSize) of
true -> <<>>; true -> <<>>;
false -> IoData false -> IoData
end end
end. end.
serialize_opts() -> initial_serialize_opts(Opts) ->
?DEFAULT_OPTIONS. maps:merge(?DEFAULT_OPTIONS, Opts).
serialize_opts(?NONE(Options)) ->
maps:merge(?DEFAULT_OPTIONS, Options);
serialize_opts(#mqtt_packet_connect{proto_ver = ProtoVer, properties = ConnProps}) -> serialize_opts(#mqtt_packet_connect{proto_ver = ProtoVer, properties = ConnProps}) ->
MaxSize = get_property('Maximum-Packet-Size', ConnProps, ?MAX_PACKET_SIZE), MaxSize = get_property('Maximum-Packet-Size', ConnProps, ?MAX_PACKET_SIZE),
#{version => ProtoVer, max_size => MaxSize}. #{version => ProtoVer, max_size => MaxSize, strict_mode => false}.
serialize_pkt(Packet, #{version := Ver, max_size := MaxSize}) -> serialize_pkt(Packet, #{version := Ver, max_size := MaxSize, strict_mode := StrictMode}) ->
IoData = serialize(Packet, Ver), IoData = serialize(Packet, Ver, StrictMode),
case is_too_large(IoData, MaxSize) of case is_too_large(IoData, MaxSize) of
true -> <<>>; true -> <<>>;
false -> IoData false -> IoData
end. end.
-spec serialize(emqx_types:packet()) -> iodata(). -spec serialize(emqx_types:packet()) -> iodata().
serialize(Packet) -> serialize(Packet, ?MQTT_PROTO_V4). serialize(Packet) -> serialize(Packet, ?MQTT_PROTO_V4, false).
-spec serialize(emqx_types:packet(), emqx_types:proto_ver()) -> iodata(). serialize(Packet, Ver) -> serialize(Packet, Ver, false).
-spec serialize(emqx_types:packet(), emqx_types:proto_ver(), boolean()) -> iodata().
serialize( serialize(
#mqtt_packet{ #mqtt_packet{
header = Header, header = Header,
variable = Variable, variable = Variable,
payload = Payload payload = Payload
}, },
Ver Ver,
StrictMode
) -> ) ->
serialize(Header, serialize_variable(Variable, Ver), serialize_payload(Payload)). serialize(
Header,
serialize_variable(Variable, Ver, StrictMode),
serialize_payload(Payload),
StrictMode
).
serialize( serialize(
#mqtt_packet_header{ #mqtt_packet_header{
@ -764,7 +810,8 @@ serialize(
retain = Retain retain = Retain
}, },
VariableBin, VariableBin,
PayloadBin PayloadBin,
_StrictMode
) when ) when
?CONNECT =< Type andalso Type =< ?AUTH ?CONNECT =< Type andalso Type =< ?AUTH
-> ->
@ -796,7 +843,8 @@ serialize_variable(
username = Username, username = Username,
password = Password password = Password
}, },
_Ver _Ver,
StrictMode
) -> ) ->
[ [
serialize_binary_data(ProtoName), serialize_binary_data(ProtoName),
@ -814,20 +862,20 @@ serialize_variable(
0:1, 0:1,
KeepAlive:16/big-unsigned-integer KeepAlive:16/big-unsigned-integer
>>, >>,
serialize_properties(Properties, ProtoVer), serialize_properties(Properties, ProtoVer, StrictMode),
serialize_utf8_string(ClientId), serialize_utf8_string(ClientId, StrictMode),
case WillFlag of case WillFlag of
true -> true ->
[ [
serialize_properties(WillProps, ProtoVer), serialize_properties(WillProps, ProtoVer, StrictMode),
serialize_utf8_string(WillTopic), serialize_utf8_string(WillTopic, StrictMode),
serialize_binary_data(WillPayload) serialize_binary_data(WillPayload)
]; ];
false -> false ->
<<>> <<>>
end, end,
serialize_utf8_string(Username, true), serialize_utf8_string(Username, true, StrictMode),
serialize_utf8_string(Password, true) serialize_utf8_string(Password, true, StrictMode)
]; ];
serialize_variable( serialize_variable(
#mqtt_packet_connack{ #mqtt_packet_connack{
@ -835,26 +883,28 @@ serialize_variable(
reason_code = ReasonCode, reason_code = ReasonCode,
properties = Properties properties = Properties
}, },
Ver Ver,
StrictMode
) -> ) ->
[AckFlags, ReasonCode, serialize_properties(Properties, Ver)]; [AckFlags, ReasonCode, serialize_properties(Properties, Ver, StrictMode)];
serialize_variable( serialize_variable(
#mqtt_packet_publish{ #mqtt_packet_publish{
topic_name = TopicName, topic_name = TopicName,
packet_id = PacketId, packet_id = PacketId,
properties = Properties properties = Properties
}, },
Ver Ver,
StrictMode
) -> ) ->
[ [
serialize_utf8_string(TopicName), serialize_utf8_string(TopicName, StrictMode),
case PacketId of case PacketId of
undefined -> <<>>; undefined -> <<>>;
_ -> <<PacketId:16/big-unsigned-integer>> _ -> <<PacketId:16/big-unsigned-integer>>
end, end,
serialize_properties(Properties, Ver) serialize_properties(Properties, Ver, StrictMode)
]; ];
serialize_variable(#mqtt_packet_puback{packet_id = PacketId}, Ver) when serialize_variable(#mqtt_packet_puback{packet_id = PacketId}, Ver, _StrictMode) when
Ver == ?MQTT_PROTO_V3; Ver == ?MQTT_PROTO_V4 Ver == ?MQTT_PROTO_V3; Ver == ?MQTT_PROTO_V4
-> ->
<<PacketId:16/big-unsigned-integer>>; <<PacketId:16/big-unsigned-integer>>;
@ -864,12 +914,13 @@ serialize_variable(
reason_code = ReasonCode, reason_code = ReasonCode,
properties = Properties properties = Properties
}, },
Ver = ?MQTT_PROTO_V5 Ver = ?MQTT_PROTO_V5,
StrictMode
) -> ) ->
[ [
<<PacketId:16/big-unsigned-integer>>, <<PacketId:16/big-unsigned-integer>>,
ReasonCode, ReasonCode,
serialize_properties(Properties, Ver) serialize_properties(Properties, Ver, StrictMode)
]; ];
serialize_variable( serialize_variable(
#mqtt_packet_subscribe{ #mqtt_packet_subscribe{
@ -877,12 +928,13 @@ serialize_variable(
properties = Properties, properties = Properties,
topic_filters = TopicFilters topic_filters = TopicFilters
}, },
Ver Ver,
StrictMode
) -> ) ->
[ [
<<PacketId:16/big-unsigned-integer>>, <<PacketId:16/big-unsigned-integer>>,
serialize_properties(Properties, Ver), serialize_properties(Properties, Ver, StrictMode),
serialize_topic_filters(subscribe, TopicFilters, Ver) serialize_topic_filters(subscribe, TopicFilters, Ver, StrictMode)
]; ];
serialize_variable( serialize_variable(
#mqtt_packet_suback{ #mqtt_packet_suback{
@ -890,11 +942,12 @@ serialize_variable(
properties = Properties, properties = Properties,
reason_codes = ReasonCodes reason_codes = ReasonCodes
}, },
Ver Ver,
StrictMode
) -> ) ->
[ [
<<PacketId:16/big-unsigned-integer>>, <<PacketId:16/big-unsigned-integer>>,
serialize_properties(Properties, Ver), serialize_properties(Properties, Ver, StrictMode),
serialize_reason_codes(ReasonCodes) serialize_reason_codes(ReasonCodes)
]; ];
serialize_variable( serialize_variable(
@ -903,12 +956,13 @@ serialize_variable(
properties = Properties, properties = Properties,
topic_filters = TopicFilters topic_filters = TopicFilters
}, },
Ver Ver,
StrictMode
) -> ) ->
[ [
<<PacketId:16/big-unsigned-integer>>, <<PacketId:16/big-unsigned-integer>>,
serialize_properties(Properties, Ver), serialize_properties(Properties, Ver, StrictMode),
serialize_topic_filters(unsubscribe, TopicFilters, Ver) serialize_topic_filters(unsubscribe, TopicFilters, Ver, StrictMode)
]; ];
serialize_variable( serialize_variable(
#mqtt_packet_unsuback{ #mqtt_packet_unsuback{
@ -916,14 +970,15 @@ serialize_variable(
properties = Properties, properties = Properties,
reason_codes = ReasonCodes reason_codes = ReasonCodes
}, },
Ver Ver,
StrictMode
) -> ) ->
[ [
<<PacketId:16/big-unsigned-integer>>, <<PacketId:16/big-unsigned-integer>>,
serialize_properties(Properties, Ver), serialize_properties(Properties, Ver, StrictMode),
serialize_reason_codes(ReasonCodes) serialize_reason_codes(ReasonCodes)
]; ];
serialize_variable(#mqtt_packet_disconnect{}, Ver) when serialize_variable(#mqtt_packet_disconnect{}, Ver, _StrictMode) when
Ver == ?MQTT_PROTO_V3; Ver == ?MQTT_PROTO_V4 Ver == ?MQTT_PROTO_V3; Ver == ?MQTT_PROTO_V4
-> ->
<<>>; <<>>;
@ -932,110 +987,115 @@ serialize_variable(
reason_code = ReasonCode, reason_code = ReasonCode,
properties = Properties properties = Properties
}, },
Ver = ?MQTT_PROTO_V5 Ver = ?MQTT_PROTO_V5,
StrictMode
) -> ) ->
[ReasonCode, serialize_properties(Properties, Ver)]; [ReasonCode, serialize_properties(Properties, Ver, StrictMode)];
serialize_variable(#mqtt_packet_disconnect{}, _Ver) -> serialize_variable(#mqtt_packet_disconnect{}, _Ver, _StrictMode) ->
<<>>; <<>>;
serialize_variable( serialize_variable(
#mqtt_packet_auth{ #mqtt_packet_auth{
reason_code = ReasonCode, reason_code = ReasonCode,
properties = Properties properties = Properties
}, },
Ver = ?MQTT_PROTO_V5 Ver = ?MQTT_PROTO_V5,
StrictMode
) -> ) ->
[ReasonCode, serialize_properties(Properties, Ver)]; [ReasonCode, serialize_properties(Properties, Ver, StrictMode)];
serialize_variable(PacketId, ?MQTT_PROTO_V3) when is_integer(PacketId) -> serialize_variable(PacketId, ?MQTT_PROTO_V3, _StrictMode) when is_integer(PacketId) ->
<<PacketId:16/big-unsigned-integer>>; <<PacketId:16/big-unsigned-integer>>;
serialize_variable(PacketId, ?MQTT_PROTO_V4) when is_integer(PacketId) -> serialize_variable(PacketId, ?MQTT_PROTO_V4, _StrictMode) when is_integer(PacketId) ->
<<PacketId:16/big-unsigned-integer>>; <<PacketId:16/big-unsigned-integer>>;
serialize_variable(undefined, _Ver) -> serialize_variable(undefined, _Ver, _StrictMode) ->
<<>>. <<>>.
serialize_payload(undefined) -> <<>>; serialize_payload(undefined) -> <<>>;
serialize_payload(Bin) -> Bin. serialize_payload(Bin) -> Bin.
serialize_properties(_Props, Ver) when Ver =/= ?MQTT_PROTO_V5 -> serialize_properties(_Props, Ver, _StrictMode) when Ver =/= ?MQTT_PROTO_V5 ->
<<>>; <<>>;
serialize_properties(Props, ?MQTT_PROTO_V5) -> serialize_properties(Props, ?MQTT_PROTO_V5, StrictMode) ->
serialize_properties(Props). serialize_properties(Props, StrictMode).
serialize_properties(undefined) -> serialize_properties(undefined, _StrictMode) ->
<<0>>; <<0>>;
serialize_properties(Props) when map_size(Props) == 0 -> serialize_properties(Props, _StrictMode) when map_size(Props) == 0 ->
<<0>>; <<0>>;
serialize_properties(Props) when is_map(Props) -> serialize_properties(Props, StrictMode) when is_map(Props) ->
Bin = <<<<(serialize_property(Prop, Val))/binary>> || {Prop, Val} <- maps:to_list(Props)>>, Bin = <<
<<(serialize_property(Prop, Val, StrictMode))/binary>>
|| {Prop, Val} <- maps:to_list(Props)
>>,
[serialize_variable_byte_integer(byte_size(Bin)), Bin]. [serialize_variable_byte_integer(byte_size(Bin)), Bin].
serialize_property(_, Disabled) when Disabled =:= disabled; Disabled =:= undefined -> serialize_property(_, Disabled, _StrictMode) when Disabled =:= disabled; Disabled =:= undefined ->
<<>>; <<>>;
serialize_property(internal_extra, _) -> serialize_property(internal_extra, _, _StrictMode) ->
<<>>; <<>>;
serialize_property('Payload-Format-Indicator', Val) -> serialize_property('Payload-Format-Indicator', Val, _StrictMode) ->
<<16#01, Val>>; <<16#01, Val>>;
serialize_property('Message-Expiry-Interval', Val) -> serialize_property('Message-Expiry-Interval', Val, _StrictMode) ->
<<16#02, Val:32/big>>; <<16#02, Val:32/big>>;
serialize_property('Content-Type', Val) -> serialize_property('Content-Type', Val, StrictMode) ->
<<16#03, (serialize_utf8_string(Val))/binary>>; <<16#03, (serialize_utf8_string(Val, StrictMode))/binary>>;
serialize_property('Response-Topic', Val) -> serialize_property('Response-Topic', Val, StrictMode) ->
<<16#08, (serialize_utf8_string(Val))/binary>>; <<16#08, (serialize_utf8_string(Val, StrictMode))/binary>>;
serialize_property('Correlation-Data', Val) -> serialize_property('Correlation-Data', Val, _StrictMode) ->
<<16#09, (byte_size(Val)):16, Val/binary>>; <<16#09, (byte_size(Val)):16, Val/binary>>;
serialize_property('Subscription-Identifier', Val) -> serialize_property('Subscription-Identifier', Val, _StrictMode) ->
<<16#0B, (serialize_variable_byte_integer(Val))/binary>>; <<16#0B, (serialize_variable_byte_integer(Val))/binary>>;
serialize_property('Session-Expiry-Interval', Val) -> serialize_property('Session-Expiry-Interval', Val, _StrictMode) ->
<<16#11, Val:32/big>>; <<16#11, Val:32/big>>;
serialize_property('Assigned-Client-Identifier', Val) -> serialize_property('Assigned-Client-Identifier', Val, StrictMode) ->
<<16#12, (serialize_utf8_string(Val))/binary>>; <<16#12, (serialize_utf8_string(Val, StrictMode))/binary>>;
serialize_property('Server-Keep-Alive', Val) -> serialize_property('Server-Keep-Alive', Val, _StrictMode) ->
<<16#13, Val:16/big>>; <<16#13, Val:16/big>>;
serialize_property('Authentication-Method', Val) -> serialize_property('Authentication-Method', Val, StrictMode) ->
<<16#15, (serialize_utf8_string(Val))/binary>>; <<16#15, (serialize_utf8_string(Val, StrictMode))/binary>>;
serialize_property('Authentication-Data', Val) -> serialize_property('Authentication-Data', Val, _StrictMode) ->
<<16#16, (iolist_size(Val)):16, Val/binary>>; <<16#16, (iolist_size(Val)):16, Val/binary>>;
serialize_property('Request-Problem-Information', Val) -> serialize_property('Request-Problem-Information', Val, _StrictMode) ->
<<16#17, Val>>; <<16#17, Val>>;
serialize_property('Will-Delay-Interval', Val) -> serialize_property('Will-Delay-Interval', Val, _StrictMode) ->
<<16#18, Val:32/big>>; <<16#18, Val:32/big>>;
serialize_property('Request-Response-Information', Val) -> serialize_property('Request-Response-Information', Val, _StrictMode) ->
<<16#19, Val>>; <<16#19, Val>>;
serialize_property('Response-Information', Val) -> serialize_property('Response-Information', Val, StrictMode) ->
<<16#1A, (serialize_utf8_string(Val))/binary>>; <<16#1A, (serialize_utf8_string(Val, StrictMode))/binary>>;
serialize_property('Server-Reference', Val) -> serialize_property('Server-Reference', Val, StrictMode) ->
<<16#1C, (serialize_utf8_string(Val))/binary>>; <<16#1C, (serialize_utf8_string(Val, StrictMode))/binary>>;
serialize_property('Reason-String', Val) -> serialize_property('Reason-String', Val, StrictMode) ->
<<16#1F, (serialize_utf8_string(Val))/binary>>; <<16#1F, (serialize_utf8_string(Val, StrictMode))/binary>>;
serialize_property('Receive-Maximum', Val) -> serialize_property('Receive-Maximum', Val, _StrictMode) ->
<<16#21, Val:16/big>>; <<16#21, Val:16/big>>;
serialize_property('Topic-Alias-Maximum', Val) -> serialize_property('Topic-Alias-Maximum', Val, _StrictMode) ->
<<16#22, Val:16/big>>; <<16#22, Val:16/big>>;
serialize_property('Topic-Alias', Val) -> serialize_property('Topic-Alias', Val, _StrictMode) ->
<<16#23, Val:16/big>>; <<16#23, Val:16/big>>;
serialize_property('Maximum-QoS', Val) -> serialize_property('Maximum-QoS', Val, _StrictMode) ->
<<16#24, Val>>; <<16#24, Val>>;
serialize_property('Retain-Available', Val) -> serialize_property('Retain-Available', Val, _StrictMode) ->
<<16#25, Val>>; <<16#25, Val>>;
serialize_property('User-Property', {Key, Val}) -> serialize_property('User-Property', {Key, Val}, StrictMode) ->
<<16#26, (serialize_utf8_pair({Key, Val}))/binary>>; <<16#26, (serialize_utf8_pair(Key, Val, StrictMode))/binary>>;
serialize_property('User-Property', Props) when is_list(Props) -> serialize_property('User-Property', Props, StrictMode) when is_list(Props) ->
<< <<
<<(serialize_property('User-Property', {Key, Val}))/binary>> <<(serialize_property('User-Property', {Key, Val}, StrictMode))/binary>>
|| {Key, Val} <- Props || {Key, Val} <- Props
>>; >>;
serialize_property('Maximum-Packet-Size', Val) -> serialize_property('Maximum-Packet-Size', Val, _StrictMode) ->
<<16#27, Val:32/big>>; <<16#27, Val:32/big>>;
serialize_property('Wildcard-Subscription-Available', Val) -> serialize_property('Wildcard-Subscription-Available', Val, _StrictMode) ->
<<16#28, Val>>; <<16#28, Val>>;
serialize_property('Subscription-Identifier-Available', Val) -> serialize_property('Subscription-Identifier-Available', Val, _StrictMode) ->
<<16#29, Val>>; <<16#29, Val>>;
serialize_property('Shared-Subscription-Available', Val) -> serialize_property('Shared-Subscription-Available', Val, _StrictMode) ->
<<16#2A, Val>>. <<16#2A, Val>>.
serialize_topic_filters(subscribe, TopicFilters, ?MQTT_PROTO_V5) -> serialize_topic_filters(subscribe, TopicFilters, ?MQTT_PROTO_V5, StrictMode) ->
<< <<
<< <<
(serialize_utf8_string(Topic))/binary, (serialize_utf8_string(Topic, StrictMode))/binary,
?RESERVED:2, ?RESERVED:2,
Rh:2, Rh:2,
(flag(Rap)):1, (flag(Rap)):1,
@ -1044,37 +1104,42 @@ serialize_topic_filters(subscribe, TopicFilters, ?MQTT_PROTO_V5) ->
>> >>
|| {Topic, #{rh := Rh, rap := Rap, nl := Nl, qos := QoS}} <- TopicFilters || {Topic, #{rh := Rh, rap := Rap, nl := Nl, qos := QoS}} <- TopicFilters
>>; >>;
serialize_topic_filters(subscribe, TopicFilters, _Ver) -> serialize_topic_filters(subscribe, TopicFilters, _Ver, StrictMode) ->
<< <<
<<(serialize_utf8_string(Topic))/binary, ?RESERVED:6, QoS:2>> <<(serialize_utf8_string(Topic, StrictMode))/binary, ?RESERVED:6, QoS:2>>
|| {Topic, #{qos := QoS}} <- TopicFilters || {Topic, #{qos := QoS}} <- TopicFilters
>>; >>;
serialize_topic_filters(unsubscribe, TopicFilters, _Ver) -> serialize_topic_filters(unsubscribe, TopicFilters, _Ver, StrictMode) ->
<<<<(serialize_utf8_string(Topic))/binary>> || Topic <- TopicFilters>>. <<<<(serialize_utf8_string(Topic, StrictMode))/binary>> || Topic <- TopicFilters>>.
serialize_reason_codes(undefined) -> serialize_reason_codes(undefined) ->
<<>>; <<>>;
serialize_reason_codes(ReasonCodes) when is_list(ReasonCodes) -> serialize_reason_codes(ReasonCodes) when is_list(ReasonCodes) ->
<<<<Code>> || Code <- ReasonCodes>>. <<<<Code>> || Code <- ReasonCodes>>.
serialize_utf8_pair({Name, Value}) -> serialize_utf8_pair(Name, Value, StrictMode) ->
<<(serialize_utf8_string(Name))/binary, (serialize_utf8_string(Value))/binary>>. <<
(serialize_utf8_string(Name, StrictMode))/binary,
(serialize_utf8_string(Value, StrictMode))/binary
>>.
serialize_binary_data(Bin) -> serialize_binary_data(Bin) ->
[<<(byte_size(Bin)):16/big-unsigned-integer>>, Bin]. [<<(byte_size(Bin)):16/big-unsigned-integer>>, Bin].
serialize_utf8_string(undefined, false) -> serialize_utf8_string(undefined, false, _StrictMode) ->
?SERIALIZE_ERR(utf8_string_undefined); ?SERIALIZE_ERR(utf8_string_undefined);
serialize_utf8_string(undefined, true) -> serialize_utf8_string(undefined, true, _StrictMode) ->
<<>>; <<>>;
serialize_utf8_string(String, _AllowNull) -> serialize_utf8_string(String, _AllowNull, StrictMode) ->
serialize_utf8_string(String). serialize_utf8_string(String, StrictMode).
serialize_utf8_string(String) -> serialize_utf8_string(String, true) ->
StringBin = unicode:characters_to_binary(String), StringBin = unicode:characters_to_binary(String),
Len = byte_size(StringBin), serialize_utf8_string(StringBin, false);
serialize_utf8_string(String, false) ->
Len = byte_size(String),
true = (Len =< 16#ffff), true = (Len =< 16#ffff),
<<Len:16/big, StringBin/binary>>. <<Len:16/big, String/binary>>.
serialize_remaining_len(I) -> serialize_remaining_len(I) ->
serialize_variable_byte_integer(I). serialize_variable_byte_integer(I).
@ -1122,6 +1187,49 @@ validate_subqos([3 | _]) -> ?PARSE_ERR(bad_subqos);
validate_subqos([_ | T]) -> validate_subqos(T); validate_subqos([_ | T]) -> validate_subqos(T);
validate_subqos([]) -> ok. validate_subqos([]) -> ok.
%% from spec: the server MAY send disconnect with reason code 0x84
%% we chose to close socket because the client is likely not talking MQTT anyway
validate_proto_name(<<"MQTT">>) ->
ok;
validate_proto_name(<<"MQIsdp">>) ->
ok;
validate_proto_name(ProtoName) ->
?PARSE_ERR(#{
cause => invalid_proto_name,
expected => <<"'MQTT' or 'MQIsdp'">>,
received => ProtoName
}).
%% MQTT-v3.1.1-[MQTT-3.1.2-3], MQTT-v5.0-[MQTT-3.1.2-3]
-compile({inline, [validate_connect_reserved/1]}).
validate_connect_reserved(0) -> ok;
validate_connect_reserved(1) -> ?PARSE_ERR(reserved_connect_flag).
-compile({inline, [validate_connect_will/3]}).
%% MQTT-v3.1.1-[MQTT-3.1.2-13], MQTT-v5.0-[MQTT-3.1.2-11]
validate_connect_will(false, _, WillQoS) when WillQoS > 0 -> ?PARSE_ERR(invalid_will_qos);
%% MQTT-v3.1.1-[MQTT-3.1.2-14], MQTT-v5.0-[MQTT-3.1.2-12]
validate_connect_will(true, _, WillQoS) when WillQoS > 2 -> ?PARSE_ERR(invalid_will_qos);
%% MQTT-v3.1.1-[MQTT-3.1.2-15], MQTT-v5.0-[MQTT-3.1.2-13]
validate_connect_will(false, WillRetain, _) when WillRetain -> ?PARSE_ERR(invalid_will_retain);
validate_connect_will(_, _, _) -> ok.
-compile({inline, [validate_connect_password_flag/4]}).
%% MQTT-v3.1
%% Username flag and password flag are not strongly related
%% https://public.dhe.ibm.com/software/dw/webservices/ws-mqtt/mqtt-v3r1.html#connect
validate_connect_password_flag(true, ?MQTT_PROTO_V3, _, _) ->
ok;
%% MQTT-v3.1.1-[MQTT-3.1.2-22]
validate_connect_password_flag(true, ?MQTT_PROTO_V4, UsernameFlag, PasswordFlag) ->
%% BUG-FOR-BUG compatible, only check when `strict-mode`
UsernameFlag orelse PasswordFlag andalso ?PARSE_ERR(invalid_password_flag);
validate_connect_password_flag(true, ?MQTT_PROTO_V5, _, _) ->
ok;
validate_connect_password_flag(_, _, _, _) ->
ok.
-compile({inline, [bool/1]}).
bool(0) -> false; bool(0) -> false;
bool(1) -> true. bool(1) -> true.

View File

@ -30,7 +30,6 @@
-export([ -export([
init/1, init/1,
run/2,
run/3, run/3,
info/1, info/1,
reset/1 reset/1
@ -62,12 +61,7 @@ init(#{count := Count, bytes := Bytes}) ->
Oct = [{oct, {Bytes, Bytes}} || ?ENABLED(Bytes)], Oct = [{oct, {Bytes, Bytes}} || ?ENABLED(Bytes)],
?GCS(maps:from_list(Cnt ++ Oct)). ?GCS(maps:from_list(Cnt ++ Oct)).
%% @doc Try to run GC based on reduntions of count or bytes. %% @doc Try to run GC based on reductions of count or bytes.
-spec run(#{cnt := pos_integer(), oct := pos_integer()}, gc_state()) ->
{boolean(), gc_state()}.
run(#{cnt := Cnt, oct := Oct}, GcSt) ->
run(Cnt, Oct, GcSt).
-spec run(pos_integer(), pos_integer(), gc_state()) -> -spec run(pos_integer(), pos_integer(), gc_state()) ->
{boolean(), gc_state()}. {boolean(), gc_state()}.
run(Cnt, Oct, ?GCS(St)) -> run(Cnt, Oct, ?GCS(St)) ->

View File

@ -44,6 +44,7 @@
'client.disconnected', 'client.disconnected',
'client.authorize', 'client.authorize',
'client.check_authz_complete', 'client.check_authz_complete',
'client.check_authn_complete',
'client.authenticate', 'client.authenticate',
'client.subscribe', 'client.subscribe',
'client.unsubscribe', 'client.unsubscribe',
@ -59,7 +60,8 @@
'message.publish', 'message.publish',
'message.puback', 'message.puback',
'message.dropped', 'message.dropped',
'message.validation_failed', 'message.transformation_failed',
'schema.validation_failed',
'message.delivered', 'message.delivered',
'message.acked', 'message.acked',
'delivery.dropped', 'delivery.dropped',
@ -183,7 +185,7 @@ when
-callback 'message.dropped'(emqx_types:message(), #{node => node()}, _Reason :: atom()) -> -callback 'message.dropped'(emqx_types:message(), #{node => node()}, _Reason :: atom()) ->
callback_result(). callback_result().
-callback 'message.validation_failed'(emqx_types:message(), #{node => node()}, _Ctx :: map()) -> -callback 'schema.validation_failed'(emqx_types:message(), #{node => node()}, _Ctx :: map()) ->
callback_result(). callback_result().
-callback 'message.delivered'(emqx_types:clientinfo(), Msg) -> fold_callback_result(Msg) when -callback 'message.delivered'(emqx_types:clientinfo(), Msg) -> fold_callback_result(Msg) when

View File

@ -19,10 +19,12 @@
-export([ -export([
init/1, init/1,
init/2, init/2,
init/3,
info/1, info/1,
info/2, info/2,
check/1,
check/2, check/2,
update/2 update/3
]). ]).
-elvis([{elvis_style, no_if_expression, disable}]). -elvis([{elvis_style, no_if_expression, disable}]).
@ -30,8 +32,12 @@
-export_type([keepalive/0]). -export_type([keepalive/0]).
-record(keepalive, { -record(keepalive, {
interval :: pos_integer(), check_interval :: pos_integer(),
statval :: non_neg_integer() %% the received packets since last keepalive check
statval :: non_neg_integer(),
%% The number of idle intervals allowed before disconnecting the client.
idle_milliseconds = 0 :: non_neg_integer(),
max_idle_millisecond :: pos_integer()
}). }).
-opaque keepalive() :: #keepalive{}. -opaque keepalive() :: #keepalive{}.
@ -39,7 +45,11 @@
%% @doc Init keepalive. %% @doc Init keepalive.
-spec init(Interval :: non_neg_integer()) -> keepalive(). -spec init(Interval :: non_neg_integer()) -> keepalive().
init(Interval) -> init(0, Interval). init(Interval) -> init(default, 0, Interval).
init(Zone, Interval) ->
RecvCnt = emqx_pd:get_counter(recv_pkt),
init(Zone, RecvCnt, Interval).
%% from mqtt-v3.1.1 specific %% from mqtt-v3.1.1 specific
%% A Keep Alive value of zero (0) has the effect of turning off the keep alive mechanism. %% A Keep Alive value of zero (0) has the effect of turning off the keep alive mechanism.
@ -53,42 +63,88 @@ init(Interval) -> init(0, Interval).
%% typically this is a few minutes. %% typically this is a few minutes.
%% The maximum value is (65535s) 18 hours 12 minutes and 15 seconds. %% The maximum value is (65535s) 18 hours 12 minutes and 15 seconds.
%% @doc Init keepalive. %% @doc Init keepalive.
-spec init(StatVal :: non_neg_integer(), Interval :: non_neg_integer()) -> keepalive() | undefined. -spec init(
init(StatVal, Interval) when Interval > 0 andalso Interval =< ?MAX_INTERVAL -> Zone :: atom(),
#keepalive{interval = Interval, statval = StatVal}; StatVal :: non_neg_integer(),
init(_, 0) -> Second :: non_neg_integer()
) -> keepalive() | undefined.
init(Zone, StatVal, Second) when Second > 0 andalso Second =< ?MAX_INTERVAL ->
#{keepalive_multiplier := Mul, keepalive_check_interval := CheckInterval} =
emqx_config:get_zone_conf(Zone, [mqtt]),
MilliSeconds = timer:seconds(Second),
Interval = emqx_utils:clamp(CheckInterval, 1000, max(MilliSeconds div 2, 1000)),
MaxIdleMs = ceil(MilliSeconds * Mul),
#keepalive{
check_interval = Interval,
statval = StatVal,
idle_milliseconds = 0,
max_idle_millisecond = MaxIdleMs
};
init(_Zone, _, 0) ->
undefined; undefined;
init(StatVal, Interval) when Interval > ?MAX_INTERVAL -> init(StatVal, ?MAX_INTERVAL). init(Zone, StatVal, Interval) when Interval > ?MAX_INTERVAL -> init(Zone, StatVal, ?MAX_INTERVAL).
%% @doc Get Info of the keepalive. %% @doc Get Info of the keepalive.
-spec info(keepalive()) -> emqx_types:infos(). -spec info(keepalive()) -> emqx_types:infos().
info(#keepalive{ info(#keepalive{
interval = Interval, check_interval = Interval,
statval = StatVal statval = StatVal,
idle_milliseconds = IdleIntervals,
max_idle_millisecond = MaxMs
}) -> }) ->
#{ #{
interval => Interval, check_interval => Interval,
statval => StatVal statval => StatVal,
idle_milliseconds => IdleIntervals,
max_idle_millisecond => MaxMs
}. }.
-spec info(interval | statval, keepalive()) -> -spec info(check_interval | statval | idle_milliseconds, keepalive()) ->
non_neg_integer(). non_neg_integer().
info(interval, #keepalive{interval = Interval}) -> info(check_interval, #keepalive{check_interval = Interval}) ->
Interval; Interval;
info(statval, #keepalive{statval = StatVal}) -> info(statval, #keepalive{statval = StatVal}) ->
StatVal; StatVal;
info(interval, undefined) -> info(idle_milliseconds, #keepalive{idle_milliseconds = Val}) ->
Val;
info(check_interval, undefined) ->
0. 0.
check(Keepalive = #keepalive{}) ->
RecvCnt = emqx_pd:get_counter(recv_pkt),
check(RecvCnt, Keepalive);
check(Keepalive) ->
{ok, Keepalive}.
%% @doc Check keepalive. %% @doc Check keepalive.
-spec check(non_neg_integer(), keepalive()) -> -spec check(non_neg_integer(), keepalive()) ->
{ok, keepalive()} | {error, timeout}. {ok, keepalive()} | {error, timeout}.
check(Val, #keepalive{statval = Val}) -> {error, timeout};
check(Val, KeepAlive) -> {ok, KeepAlive#keepalive{statval = Val}}. check(
NewVal,
#keepalive{
statval = NewVal,
idle_milliseconds = IdleAcc,
check_interval = Interval,
max_idle_millisecond = Max
}
) when IdleAcc + Interval >= Max ->
{error, timeout};
check(
NewVal,
#keepalive{
statval = NewVal,
idle_milliseconds = IdleAcc,
check_interval = Interval
} = KeepAlive
) ->
{ok, KeepAlive#keepalive{statval = NewVal, idle_milliseconds = IdleAcc + Interval}};
check(NewVal, #keepalive{} = KeepAlive) ->
{ok, KeepAlive#keepalive{statval = NewVal, idle_milliseconds = 0}}.
%% @doc Update keepalive. %% @doc Update keepalive.
%% The statval of the previous keepalive will be used, %% The statval of the previous keepalive will be used,
%% and normal checks will begin from the next cycle. %% and normal checks will begin from the next cycle.
-spec update(non_neg_integer(), keepalive() | undefined) -> keepalive() | undefined. -spec update(atom(), non_neg_integer(), keepalive() | undefined) -> keepalive() | undefined.
update(Interval, undefined) -> init(0, Interval); update(Zone, Interval, undefined) -> init(Zone, 0, Interval);
update(Interval, #keepalive{statval = StatVal}) -> init(StatVal, Interval). update(Zone, Interval, #keepalive{statval = StatVal}) -> init(Zone, StatVal, Interval).

View File

@ -212,16 +212,29 @@ short_paths_fields() ->
short_paths_fields(Importance) -> short_paths_fields(Importance) ->
[ [
{Name, {Name,
?HOCON(rate_type(), #{ ?HOCON(
desc => ?DESC(Name), rate_type(),
required => false, maps:merge(
importance => Importance, #{
example => Example desc => ?DESC(Name),
})} required => false,
importance => Importance,
example => Example
},
short_paths_fields_extra(Name)
)
)}
|| {Name, Example} <- || {Name, Example} <-
lists:zip(short_paths(), [<<"1000/s">>, <<"1000/s">>, <<"100MB/s">>]) lists:zip(short_paths(), [<<"1000/s">>, <<"1000/s">>, <<"100MB/s">>])
]. ].
short_paths_fields_extra(max_conn_rate) ->
#{
default => infinity
};
short_paths_fields_extra(_Name) ->
#{}.
desc(limiter) -> desc(limiter) ->
"Settings for the rate limiter."; "Settings for the rate limiter.";
desc(node_opts) -> desc(node_opts) ->

View File

@ -64,6 +64,17 @@
-export_type([listener_id/0]). -export_type([listener_id/0]).
-dialyzer(
{no_unknown, [
is_running/3,
current_conns/3,
do_stop_listener/3,
do_start_listener/4,
do_update_listener/4,
quic_listener_conf_rollback/3
]}
).
-type listener_id() :: atom() | binary(). -type listener_id() :: atom() | binary().
-type listener_type() :: tcp | ssl | ws | wss | quic | dtls. -type listener_type() :: tcp | ssl | ws | wss | quic | dtls.
@ -124,7 +135,7 @@ format_raw_listeners({Type0, Conf}) ->
Bind = parse_bind(LConf0), Bind = parse_bind(LConf0),
MaxConn = maps:get(<<"max_connections">>, LConf0, default_max_conn()), MaxConn = maps:get(<<"max_connections">>, LConf0, default_max_conn()),
Running = is_running(Type, listener_id(Type, LName), LConf0#{bind => Bind}), Running = is_running(Type, listener_id(Type, LName), LConf0#{bind => Bind}),
LConf1 = maps:without([<<"authentication">>, <<"zone">>], LConf0), LConf1 = maps:without([<<"authentication">>], LConf0),
LConf2 = maps:put(<<"running">>, Running, LConf1), LConf2 = maps:put(<<"running">>, Running, LConf1),
CurrConn = CurrConn =
case Running of case Running of
@ -421,7 +432,7 @@ do_start_listener(Type, Name, Id, #{bind := ListenOn} = Opts) when ?ESOCKD_LISTE
esockd:open( esockd:open(
Id, Id,
ListenOn, ListenOn,
merge_default(esockd_opts(Id, Type, Name, Opts)) merge_default(esockd_opts(Id, Type, Name, Opts, _OldOpts = undefined))
); );
%% Start MQTT/WS listener %% Start MQTT/WS listener
do_start_listener(Type, Name, Id, Opts) when ?COWBOY_LISTENER(Type) -> do_start_listener(Type, Name, Id, Opts) when ?COWBOY_LISTENER(Type) ->
@ -465,7 +476,7 @@ do_update_listener(Type, Name, OldConf, NewConf = #{bind := ListenOn}) when
Id = listener_id(Type, Name), Id = listener_id(Type, Name),
case maps:get(bind, OldConf) of case maps:get(bind, OldConf) of
ListenOn -> ListenOn ->
esockd:set_options({Id, ListenOn}, esockd_opts(Id, Type, Name, NewConf)); esockd:set_options({Id, ListenOn}, esockd_opts(Id, Type, Name, NewConf, OldConf));
_Different -> _Different ->
%% TODO %% TODO
%% Again, we're not strictly required to drop live connections in this case. %% Again, we're not strictly required to drop live connections in this case.
@ -526,6 +537,7 @@ pre_config_update([?ROOT_KEY, _Type, _Name], {update, _Request}, undefined) ->
pre_config_update([?ROOT_KEY, Type, Name], {update, Request}, RawConf) -> pre_config_update([?ROOT_KEY, Type, Name], {update, Request}, RawConf) ->
RawConf1 = emqx_utils_maps:deep_merge(RawConf, Request), RawConf1 = emqx_utils_maps:deep_merge(RawConf, Request),
RawConf2 = ensure_override_limiter_conf(RawConf1, Request), RawConf2 = ensure_override_limiter_conf(RawConf1, Request),
ok = assert_zone_exists(RawConf2),
{ok, convert_certs(Type, Name, RawConf2)}; {ok, convert_certs(Type, Name, RawConf2)};
pre_config_update([?ROOT_KEY, _Type, _Name], {action, _Action, Updated}, RawConf) -> pre_config_update([?ROOT_KEY, _Type, _Name], {action, _Action, Updated}, RawConf) ->
{ok, emqx_utils_maps:deep_merge(RawConf, Updated)}; {ok, emqx_utils_maps:deep_merge(RawConf, Updated)};
@ -576,7 +588,7 @@ perform_listener_change(update, {{Type, Name, ConfOld}, {_, _, ConfNew}}) ->
perform_listener_change(stop, {Type, Name, Conf}) -> perform_listener_change(stop, {Type, Name, Conf}) ->
stop_listener(Type, Name, Conf). stop_listener(Type, Name, Conf).
esockd_opts(ListenerId, Type, Name, Opts0) -> esockd_opts(ListenerId, Type, Name, Opts0, OldOpts) ->
Opts1 = maps:with([acceptors, max_connections, proxy_protocol, proxy_protocol_timeout], Opts0), Opts1 = maps:with([acceptors, max_connections, proxy_protocol, proxy_protocol_timeout], Opts0),
Limiter = limiter(Opts0), Limiter = limiter(Opts0),
Opts2 = Opts2 =
@ -608,9 +620,11 @@ esockd_opts(ListenerId, Type, Name, Opts0) ->
tcp -> tcp ->
Opts3#{tcp_options => tcp_opts(Opts0)}; Opts3#{tcp_options => tcp_opts(Opts0)};
ssl -> ssl ->
OptsWithCRL = inject_crl_config(Opts0), OptsWithCRL = inject_crl_config(Opts0, OldOpts),
OptsWithSNI = inject_sni_fun(ListenerId, OptsWithCRL), OptsWithSNI = inject_sni_fun(ListenerId, OptsWithCRL),
SSLOpts = ssl_opts(OptsWithSNI), OptsWithRootFun = inject_root_fun(OptsWithSNI),
OptsWithVerifyFun = inject_verify_fun(OptsWithRootFun),
SSLOpts = ssl_opts(OptsWithVerifyFun),
Opts3#{ssl_options => SSLOpts, tcp_options => tcp_opts(Opts0)} Opts3#{ssl_options => SSLOpts, tcp_options => tcp_opts(Opts0)}
end end
). ).
@ -634,8 +648,18 @@ ranch_opts(Type, Opts = #{bind := ListenOn}) ->
MaxConnections = maps:get(max_connections, Opts, 1024), MaxConnections = maps:get(max_connections, Opts, 1024),
SocketOpts = SocketOpts =
case Type of case Type of
wss -> tcp_opts(Opts) ++ proplists:delete(handshake_timeout, ssl_opts(Opts)); wss ->
ws -> tcp_opts(Opts) tcp_opts(Opts) ++
lists:filter(
fun
({partial_chain, _}) -> false;
({handshake_timeout, _}) -> false;
(_) -> true
end,
ssl_opts(Opts)
);
ws ->
tcp_opts(Opts)
end, end,
#{ #{
num_acceptors => NumAcceptors, num_acceptors => NumAcceptors,
@ -884,6 +908,11 @@ convert_certs(Type, Name, Conf) ->
filter_stacktrace({Reason, _Stacktrace}) -> Reason; filter_stacktrace({Reason, _Stacktrace}) -> Reason;
filter_stacktrace(Reason) -> Reason. filter_stacktrace(Reason) -> Reason.
assert_zone_exists(#{<<"zone">> := Zone}) ->
emqx_config_zones:assert_zone_exists(Zone);
assert_zone_exists(_) ->
ok.
%% limiter config should override, not merge %% limiter config should override, not merge
ensure_override_limiter_conf(Conf, #{<<"limiter">> := Limiter}) -> ensure_override_limiter_conf(Conf, #{<<"limiter">> := Limiter}) ->
Conf#{<<"limiter">> => Limiter}; Conf#{<<"limiter">> => Limiter};
@ -956,13 +985,18 @@ quic_listener_optional_settings() ->
stateless_operation_expiration_ms stateless_operation_expiration_ms
]. ].
inject_root_fun(#{ssl_options := SSLOpts} = Opts) ->
Opts#{ssl_options := emqx_tls_lib:maybe_inject_ssl_fun(root_fun, SSLOpts)}.
inject_verify_fun(#{ssl_options := SSLOpts} = Opts) ->
Opts#{ssl_options := emqx_tls_lib:maybe_inject_ssl_fun(verify_fun, SSLOpts)}.
inject_sni_fun(ListenerId, Conf = #{ssl_options := #{ocsp := #{enable_ocsp_stapling := true}}}) -> inject_sni_fun(ListenerId, Conf = #{ssl_options := #{ocsp := #{enable_ocsp_stapling := true}}}) ->
emqx_ocsp_cache:inject_sni_fun(ListenerId, Conf); emqx_ocsp_cache:inject_sni_fun(ListenerId, Conf);
inject_sni_fun(_ListenerId, Conf) -> inject_sni_fun(_ListenerId, Conf) ->
Conf. Conf.
inject_crl_config( inject_crl_config(
Conf = #{ssl_options := #{enable_crl_check := true} = SSLOpts} Conf = #{ssl_options := #{enable_crl_check := true} = SSLOpts}, _OldOpts
) -> ) ->
HTTPTimeout = emqx_config:get([crl_cache, http_timeout], timer:seconds(15)), HTTPTimeout = emqx_config:get([crl_cache, http_timeout], timer:seconds(15)),
Conf#{ Conf#{
@ -972,7 +1006,16 @@ inject_crl_config(
crl_cache => {emqx_ssl_crl_cache, {internal, [{http, HTTPTimeout}]}} crl_cache => {emqx_ssl_crl_cache, {internal, [{http, HTTPTimeout}]}}
} }
}; };
inject_crl_config(Conf) -> inject_crl_config(#{ssl_options := SSLOpts0} = Conf0, #{} = OldOpts) ->
%% Note: we must set crl options to `undefined' to unset them. Otherwise,
%% `esockd' will retain such options when `esockd:merge_opts/2' is called and the SSL
%% options were previously enabled.
WasEnabled = emqx_utils_maps:deep_get([ssl_options, enable_crl_check], OldOpts, false),
Undefine = fun(Acc, K) -> emqx_utils_maps:put_if(Acc, K, undefined, WasEnabled) end,
SSLOpts1 = Undefine(SSLOpts0, crl_check),
SSLOpts = Undefine(SSLOpts1, crl_cache),
Conf0#{ssl_options := SSLOpts};
inject_crl_config(Conf, undefined = _OldOpts) ->
Conf. Conf.
maybe_unregister_ocsp_stapling_refresh( maybe_unregister_ocsp_stapling_refresh(
@ -995,7 +1038,6 @@ ensure_max_conns(<<"infinity">>) -> <<"infinity">>;
ensure_max_conns(MaxConn) when is_binary(MaxConn) -> binary_to_integer(MaxConn); ensure_max_conns(MaxConn) when is_binary(MaxConn) -> binary_to_integer(MaxConn);
ensure_max_conns(MaxConn) -> MaxConn. ensure_max_conns(MaxConn) -> MaxConn.
-spec quic_listen_on(X :: any()) -> quicer:listen_on().
quic_listen_on(Bind) -> quic_listen_on(Bind) ->
case Bind of case Bind of
{Addr, Port} when tuple_size(Addr) == 4 -> {Addr, Port} when tuple_size(Addr) == 4 ->
@ -1014,8 +1056,8 @@ to_quicer_listener_opts(Opts) ->
SSLOpts = maps:from_list(ssl_opts(Opts)), SSLOpts = maps:from_list(ssl_opts(Opts)),
Opts1 = maps:filter( Opts1 = maps:filter(
fun fun
(cacertfile, undefined) -> fasle; (cacertfile, undefined) -> false;
(password, undefined) -> fasle; (password, undefined) -> false;
(_, _) -> true (_, _) -> true
end, end,
Opts Opts

View File

@ -25,7 +25,7 @@
-export([start_link/0]). -export([start_link/0]).
%% throttler API %% throttler API
-export([allow/1]). -export([allow/2]).
%% gen_server callbacks %% gen_server callbacks
-export([ -export([
@ -40,23 +40,29 @@
-define(SEQ_ID(Msg), {?MODULE, Msg}). -define(SEQ_ID(Msg), {?MODULE, Msg}).
-define(NEW_SEQ, atomics:new(1, [{signed, false}])). -define(NEW_SEQ, atomics:new(1, [{signed, false}])).
-define(GET_SEQ(Msg), persistent_term:get(?SEQ_ID(Msg), undefined)). -define(GET_SEQ(Msg), persistent_term:get(?SEQ_ID(Msg), undefined)).
-define(ERASE_SEQ(Msg), persistent_term:erase(?SEQ_ID(Msg))).
-define(RESET_SEQ(SeqRef), atomics:put(SeqRef, 1, 0)). -define(RESET_SEQ(SeqRef), atomics:put(SeqRef, 1, 0)).
-define(INC_SEQ(SeqRef), atomics:add(SeqRef, 1, 1)). -define(INC_SEQ(SeqRef), atomics:add(SeqRef, 1, 1)).
-define(GET_DROPPED(SeqRef), atomics:get(SeqRef, 1) - 1). -define(GET_DROPPED(SeqRef), atomics:get(SeqRef, 1) - 1).
-define(IS_ALLOWED(SeqRef), atomics:add_get(SeqRef, 1, 1) =:= 1). -define(IS_ALLOWED(SeqRef), atomics:add_get(SeqRef, 1, 1) =:= 1).
-define(NEW_THROTTLE(Msg, SeqRef), persistent_term:put(?SEQ_ID(Msg), SeqRef)).
-define(MSGS_LIST, emqx:get_config([log, throttling, msgs], [])). -define(MSGS_LIST, emqx:get_config([log, throttling, msgs], [])).
-define(TIME_WINDOW_MS, timer:seconds(emqx:get_config([log, throttling, time_window], 60))). -define(TIME_WINDOW_MS, timer:seconds(emqx:get_config([log, throttling, time_window], 60))).
-spec allow(atom()) -> boolean(). %% @doc Check if a throttled log message is allowed to pass down to the logger this time.
allow(Msg) when is_atom(Msg) -> %% The Msg has to be an atom, and the second argument `UniqueKey' should be `undefined'
%% for predefined message IDs.
%% For relatively static resources created from configurations such as data integration
%% resource IDs `UniqueKey' should be of `binary()' type.
-spec allow(atom(), undefined | binary()) -> boolean().
allow(Msg, UniqueKey) when
is_atom(Msg) andalso (is_binary(UniqueKey) orelse UniqueKey =:= undefined)
->
case emqx_logger:get_primary_log_level() of case emqx_logger:get_primary_log_level() of
debug -> debug ->
true; true;
_ -> _ ->
do_allow(Msg) do_allow(Msg, UniqueKey)
end. end.
-spec start_link() -> startlink_ret(). -spec start_link() -> startlink_ret().
@ -68,7 +74,8 @@ start_link() ->
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
init([]) -> init([]) ->
ok = lists:foreach(fun(Msg) -> ?NEW_THROTTLE(Msg, ?NEW_SEQ) end, ?MSGS_LIST), process_flag(trap_exit, true),
ok = lists:foreach(fun new_throttler/1, ?MSGS_LIST),
CurrentPeriodMs = ?TIME_WINDOW_MS, CurrentPeriodMs = ?TIME_WINDOW_MS,
TimerRef = schedule_refresh(CurrentPeriodMs), TimerRef = schedule_refresh(CurrentPeriodMs),
{ok, #{timer_ref => TimerRef, current_period_ms => CurrentPeriodMs}}. {ok, #{timer_ref => TimerRef, current_period_ms => CurrentPeriodMs}}.
@ -86,16 +93,22 @@ handle_info(refresh, #{current_period_ms := PeriodMs} = State) ->
DroppedStats = lists:foldl( DroppedStats = lists:foldl(
fun(Msg, Acc) -> fun(Msg, Acc) ->
case ?GET_SEQ(Msg) of case ?GET_SEQ(Msg) of
%% Should not happen, unless the static ids list is updated at run-time.
undefined -> undefined ->
?NEW_THROTTLE(Msg, ?NEW_SEQ), %% Should not happen, unless the static ids list is updated at run-time.
new_throttler(Msg),
?tp(log_throttler_new_msg, #{throttled_msg => Msg}), ?tp(log_throttler_new_msg, #{throttled_msg => Msg}),
Acc; Acc;
SeqMap when is_map(SeqMap) ->
maps:fold(
fun(Key, Ref, Acc0) ->
ID = iolist_to_binary([atom_to_binary(Msg), $:, Key]),
drop_stats(Ref, ID, Acc0)
end,
Acc,
SeqMap
);
SeqRef -> SeqRef ->
Dropped = ?GET_DROPPED(SeqRef), drop_stats(SeqRef, Msg, Acc)
ok = ?RESET_SEQ(SeqRef),
?tp(log_throttler_dropped, #{dropped_count => Dropped, throttled_msg => Msg}),
maybe_add_dropped(Msg, Dropped, Acc)
end end
end, end,
#{}, #{},
@ -112,7 +125,16 @@ handle_info(Info, State) ->
?SLOG(error, #{msg => "unxpected_info", info => Info}), ?SLOG(error, #{msg => "unxpected_info", info => Info}),
{noreply, State}. {noreply, State}.
drop_stats(SeqRef, Msg, Acc) ->
Dropped = ?GET_DROPPED(SeqRef),
ok = ?RESET_SEQ(SeqRef),
?tp(log_throttler_dropped, #{dropped_count => Dropped, throttled_msg => Msg}),
maybe_add_dropped(Msg, Dropped, Acc).
terminate(_Reason, _State) -> terminate(_Reason, _State) ->
%% atomics do not have delete/remove/release/deallocate API
%% after the reference is garbage-collected the resource is released
lists:foreach(fun(Msg) -> ?ERASE_SEQ(Msg) end, ?MSGS_LIST),
ok. ok.
code_change(_OldVsn, State, _Extra) -> code_change(_OldVsn, State, _Extra) ->
@ -122,17 +144,27 @@ code_change(_OldVsn, State, _Extra) ->
%% internal functions %% internal functions
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
do_allow(Msg) -> do_allow(Msg, UniqueKey) ->
case persistent_term:get(?SEQ_ID(Msg), undefined) of case persistent_term:get(?SEQ_ID(Msg), undefined) of
undefined -> undefined ->
%% This is either a race condition (emqx_log_throttler is not started yet) %% This is either a race condition (emqx_log_throttler is not started yet)
%% or a developer mistake (msg used in ?SLOG_THROTTLE/2,3 macro is %% or a developer mistake (msg used in ?SLOG_THROTTLE/2,3 macro is
%% not added to the default value of `log.throttling.msgs`. %% not added to the default value of `log.throttling.msgs`.
?SLOG(info, #{ ?SLOG(debug, #{
msg => "missing_log_throttle_sequence", msg => "log_throttle_disabled",
throttled_msg => Msg throttled_msg => Msg
}), }),
true; true;
%% e.g: unrecoverable msg throttle according resource_id
SeqMap when is_map(SeqMap) ->
case maps:find(UniqueKey, SeqMap) of
{ok, SeqRef} ->
?IS_ALLOWED(SeqRef);
error ->
SeqRef = ?NEW_SEQ,
new_throttler(Msg, SeqMap#{UniqueKey => SeqRef}),
true
end;
SeqRef -> SeqRef ->
?IS_ALLOWED(SeqRef) ?IS_ALLOWED(SeqRef)
end. end.
@ -154,3 +186,11 @@ maybe_log_dropped(_DroppedStats, _PeriodMs) ->
schedule_refresh(PeriodMs) -> schedule_refresh(PeriodMs) ->
?tp(log_throttler_sched_refresh, #{new_period_ms => PeriodMs}), ?tp(log_throttler_sched_refresh, #{new_period_ms => PeriodMs}),
erlang:send_after(PeriodMs, ?MODULE, refresh). erlang:send_after(PeriodMs, ?MODULE, refresh).
new_throttler(unrecoverable_resource_error = Msg) ->
new_throttler(Msg, #{});
new_throttler(Msg) ->
new_throttler(Msg, ?NEW_SEQ).
new_throttler(Msg, AtomicOrEmptyMap) ->
persistent_term:put(?SEQ_ID(Msg), AtomicOrEmptyMap).

View File

@ -34,6 +34,9 @@
%% For CLI HTTP API outputs %% For CLI HTTP API outputs
-export([best_effort_json/1, best_effort_json/2, best_effort_json_obj/1]). -export([best_effort_json/1, best_effort_json/2, best_effort_json_obj/1]).
%% For emqx_trace_json_formatter
-export([format_msg/3]).
-ifdef(TEST). -ifdef(TEST).
-include_lib("proper/include/proper.hrl"). -include_lib("proper/include/proper.hrl").
-include_lib("eunit/include/eunit.hrl"). -include_lib("eunit/include/eunit.hrl").
@ -52,7 +55,8 @@
depth => pos_integer() | unlimited, depth => pos_integer() | unlimited,
report_cb => logger:report_cb(), report_cb => logger:report_cb(),
single_line => boolean(), single_line => boolean(),
chars_limit => unlimited | pos_integer() chars_limit => unlimited | pos_integer(),
payload_encode => text | hidden | hex
}. }.
-define(IS_STRING(String), (is_list(String) orelse is_binary(String))). -define(IS_STRING(String), (is_list(String) orelse is_binary(String))).
@ -73,7 +77,9 @@ best_effort_json_obj(Input) ->
best_effort_json_obj(Input, Config). best_effort_json_obj(Input, Config).
-spec format(logger:log_event(), config()) -> iodata(). -spec format(logger:log_event(), config()) -> iodata().
format(#{level := Level, msg := Msg, meta := Meta}, Config0) when is_map(Config0) -> format(#{level := _Level, msg := _Msg, meta := _Meta} = Entry, Config0) when is_map(Config0) ->
#{level := Level, msg := Msg, meta := Meta} =
emqx_logger_textfmt:evaluate_lazy_values_if_dbg_level(Entry),
Config = add_default_config(Config0), Config = add_default_config(Config0),
[format(Msg, Meta#{level => Level}, Config), "\n"]. [format(Msg, Meta#{level => Level}, Config), "\n"].
@ -98,7 +104,8 @@ format(Msg, Meta, Config) ->
maybe_format_msg(undefined, _Meta, _Config) -> maybe_format_msg(undefined, _Meta, _Config) ->
#{}; #{};
maybe_format_msg({report, Report} = Msg, #{report_cb := Cb} = Meta, Config) -> maybe_format_msg({report, Report0} = Msg, #{report_cb := Cb} = Meta, Config) ->
Report = emqx_logger_textfmt:try_encode_meta(Report0, Config),
case is_map(Report) andalso Cb =:= ?DEFAULT_FORMATTER of case is_map(Report) andalso Cb =:= ?DEFAULT_FORMATTER of
true -> true ->
%% reporting a map without a customised format function %% reporting a map without a customised format function
@ -216,7 +223,7 @@ best_effort_unicode(Input, Config) ->
best_effort_json_obj(List, Config) when is_list(List) -> best_effort_json_obj(List, Config) when is_list(List) ->
try try
json_obj(maps:from_list(List), Config) json_obj(convert_tuple_list_to_map(List), Config)
catch catch
_:_ -> _:_ ->
[json(I, Config) || I <- List] [json(I, Config) || I <- List]
@ -229,6 +236,16 @@ best_effort_json_obj(Map, Config) ->
do_format_msg("~p", [Map], Config) do_format_msg("~p", [Map], Config)
end. end.
%% This function will throw if the list do not only contain tuples or if there
%% are duplicate keys.
convert_tuple_list_to_map(List) ->
%% Crash if this is not a tuple list
CandidateMap = maps:from_list(List),
%% Crash if there are duplicates
NumberOfItems = length(List),
NumberOfItems = maps:size(CandidateMap),
CandidateMap.
json(A, _) when is_atom(A) -> A; json(A, _) when is_atom(A) -> A;
json(I, _) when is_integer(I) -> I; json(I, _) when is_integer(I) -> I;
json(F, _) when is_float(F) -> F; json(F, _) when is_float(F) -> F;
@ -255,6 +272,8 @@ json(L, Config) when is_list(L) ->
end; end;
json(Map, Config) when is_map(Map) -> json(Map, Config) when is_map(Map) ->
best_effort_json_obj(Map, Config); best_effort_json_obj(Map, Config);
json({'$array$', List}, Config) when is_list(List) ->
[json(I, Config) || I <- List];
json(Term, Config) -> json(Term, Config) ->
do_format_msg("~p", [Term], Config). do_format_msg("~p", [Term], Config).
@ -275,6 +294,7 @@ json_obj_root(Data0, Config) ->
_ -> _ ->
json(Msg1, Config) json(Msg1, Config)
end, end,
MFA = emqx_utils:format_mfal(Data0, Config),
Data = Data =
maps:fold( maps:fold(
fun(K, V, D) -> fun(K, V, D) ->
@ -283,12 +303,12 @@ json_obj_root(Data0, Config) ->
end, end,
[], [],
maps:without( maps:without(
[time, gl, file, report_cb, msg, '$kind', level, is_trace], Data0 [time, gl, file, report_cb, msg, '$kind', level, mfa, is_trace], Data0
) )
), ),
lists:filter( lists:filter(
fun({_, V}) -> V =/= undefined end, fun({_, V}) -> V =/= undefined end,
[{time, format_ts(Time, Config)}, {level, Level}, {msg, Msg}] [{time, format_ts(Time, Config)}, {level, Level}, {msg, Msg}, {mfa, MFA}]
) ++ Data. ) ++ Data.
format_ts(Ts, #{timestamp_format := rfc3339, time_offset := Offset}) when is_integer(Ts) -> format_ts(Ts, #{timestamp_format := rfc3339, time_offset := Offset}) when is_integer(Ts) ->
@ -433,6 +453,36 @@ best_effort_json_test() ->
<<"[\n {\n \"key\" : [\n \n ]\n }\n]">>, <<"[\n {\n \"key\" : [\n \n ]\n }\n]">>,
best_effort_json([#{key => []}]) best_effort_json([#{key => []}])
), ),
%% List is IO Data
?assertMatch(
#{<<"what">> := <<"hej\n">>},
emqx_utils_json:decode(emqx_logger_jsonfmt:best_effort_json(#{what => [<<"hej">>, 10]}))
),
%% Force list to be interpreted as an array
?assertMatch(
#{<<"what">> := [<<"hej">>, 10]},
emqx_utils_json:decode(
emqx_logger_jsonfmt:best_effort_json(#{what => {'$array$', [<<"hej">>, 10]}})
)
),
%% IO Data inside an array
?assertMatch(
#{<<"what">> := [<<"hej">>, 10, <<"hej\n">>]},
emqx_utils_json:decode(
emqx_logger_jsonfmt:best_effort_json(#{
what => {'$array$', [<<"hej">>, 10, [<<"hej">>, 10]]}
})
)
),
%% Array inside an array
?assertMatch(
#{<<"what">> := [<<"hej">>, 10, [<<"hej">>, 10]]},
emqx_utils_json:decode(
emqx_logger_jsonfmt:best_effort_json(#{
what => {'$array$', [<<"hej">>, 10, {'$array$', [<<"hej">>, 10]}]}
})
)
),
ok. ok.
config() -> config() ->

View File

@ -16,18 +16,24 @@
-module(emqx_logger_textfmt). -module(emqx_logger_textfmt).
-include("emqx_trace.hrl").
-export([format/2]). -export([format/2]).
-export([check_config/1]). -export([check_config/1]).
-export([try_format_unicode/1]). -export([try_format_unicode/1, try_encode_meta/2]).
%% Used in the other log formatters
-export([evaluate_lazy_values_if_dbg_level/1, evaluate_lazy_values/1]).
check_config(X) -> logger_formatter:check_config(maps:without([timestamp_format], X)). check_config(X) ->
logger_formatter:check_config(maps:without([timestamp_format, with_mfa, payload_encode], X)).
%% Principle here is to delegate the formatting to logger_formatter:format/2 %% Principle here is to delegate the formatting to logger_formatter:format/2
%% as much as possible, and only enrich the report with clientid, peername, topic, username %% as much as possible, and only enrich the report with clientid, peername, topic, username
format(#{msg := {report, ReportMap}, meta := Meta} = Event, Config) when is_map(ReportMap) -> format(#{msg := {report, ReportMap0}, meta := _Meta} = Event0, Config) when is_map(ReportMap0) ->
#{msg := {report, ReportMap}, meta := Meta} = Event = evaluate_lazy_values_if_dbg_level(Event0),
%% The most common case, when entering from SLOG macro %% The most common case, when entering from SLOG macro
%% i.e. logger:log(Level, #{msg => "my_msg", foo => bar}) %% i.e. logger:log(Level, #{msg => "my_msg", foo => bar})
ReportList = enrich_report(ReportMap, Meta), ReportList = enrich_report(ReportMap, Meta, Config),
Report = Report =
case is_list_report_acceptable(Meta) of case is_list_report_acceptable(Meta) of
true -> true ->
@ -35,17 +41,50 @@ format(#{msg := {report, ReportMap}, meta := Meta} = Event, Config) when is_map(
false -> false ->
maps:from_list(ReportList) maps:from_list(ReportList)
end, end,
fmt(Event#{msg := {report, Report}}, Config); fmt(Event#{msg := {report, Report}}, maps:remove(with_mfa, Config));
format(#{msg := {string, String}} = Event, Config) -> format(#{msg := {string, String}} = Event, Config) ->
%% copied from logger_formatter:format/2 %% copied from logger_formatter:format/2
%% unsure how this case is triggered %% unsure how this case is triggered
format(Event#{msg => {"~ts ", [String]}}, Config); format(Event#{msg => {"~ts ", [String]}}, maps:remove(with_mfa, Config));
format(#{msg := Msg0, meta := Meta} = Event, Config) -> format(#{msg := _Msg, meta := _Meta} = Event0, Config) ->
#{msg := Msg0, meta := Meta} = Event1 = evaluate_lazy_values_if_dbg_level(Event0),
%% For format strings like logger:log(Level, "~p", [Var]) %% For format strings like logger:log(Level, "~p", [Var])
%% and logger:log(Level, "message", #{key => value}) %% and logger:log(Level, "message", #{key => value})
Msg1 = enrich_client_info(Msg0, Meta), Msg1 = enrich_client_info(Msg0, Meta),
Msg2 = enrich_topic(Msg1, Meta), Msg2 = enrich_mfa(Msg1, Meta, Config),
fmt(Event#{msg := Msg2}, Config). Msg3 = enrich_topic(Msg2, Meta),
fmt(Event1#{msg := Msg3}, maps:remove(with_mfa, Config)).
enrich_mfa({Fmt, Args}, Data, #{with_mfa := true} = Config) when is_list(Fmt) ->
{Fmt ++ " mfa: ~ts", Args ++ [emqx_utils:format_mfal(Data, Config)]};
enrich_mfa(Msg, _, _) ->
Msg.
%% Most log entries with lazy values are trace events with level debug. So to
%% be more efficient we only search for lazy values to evaluate in the entries
%% with level debug in the main log formatters.
evaluate_lazy_values_if_dbg_level(#{level := debug} = Map) ->
evaluate_lazy_values(Map);
evaluate_lazy_values_if_dbg_level(Map) ->
Map.
evaluate_lazy_values(Map) when is_map(Map) ->
maps:map(fun evaluate_lazy_values_kv/2, Map);
evaluate_lazy_values({report, Report}) ->
{report, evaluate_lazy_values(Report)};
evaluate_lazy_values(V) ->
V.
evaluate_lazy_values_kv(_K, #emqx_trace_format_func_data{function = Formatter, data = V}) ->
try
NewV = Formatter(V),
evaluate_lazy_values(NewV)
catch
_:_ ->
V
end;
evaluate_lazy_values_kv(_K, V) ->
evaluate_lazy_values(V).
fmt(#{meta := #{time := Ts}} = Data, Config) -> fmt(#{meta := #{time := Ts}} = Data, Config) ->
Timestamp = Timestamp =
@ -69,9 +108,10 @@ is_list_report_acceptable(#{report_cb := Cb}) ->
is_list_report_acceptable(_) -> is_list_report_acceptable(_) ->
false. false.
enrich_report(ReportRaw, Meta) -> enrich_report(ReportRaw0, Meta, Config) ->
%% clientid and peername always in emqx_conn's process metadata. %% clientid and peername always in emqx_conn's process metadata.
%% topic and username can be put in meta using ?SLOG/3, or put in msg's report by ?SLOG/2 %% topic and username can be put in meta using ?SLOG/3, or put in msg's report by ?SLOG/2
ReportRaw = try_encode_meta(ReportRaw0, Config),
Topic = Topic =
case maps:get(topic, Meta, undefined) of case maps:get(topic, Meta, undefined) of
undefined -> maps:get(topic, ReportRaw, undefined); undefined -> maps:get(topic, ReportRaw, undefined);
@ -85,6 +125,7 @@ enrich_report(ReportRaw, Meta) ->
ClientId = maps:get(clientid, Meta, undefined), ClientId = maps:get(clientid, Meta, undefined),
Peer = maps:get(peername, Meta, undefined), Peer = maps:get(peername, Meta, undefined),
Msg = maps:get(msg, ReportRaw, undefined), Msg = maps:get(msg, ReportRaw, undefined),
MFA = emqx_utils:format_mfal(Meta, Config),
%% TODO: move all tags to Meta so we can filter traces %% TODO: move all tags to Meta so we can filter traces
%% based on tags (currently not supported) %% based on tags (currently not supported)
Tag = maps:get(tag, ReportRaw, maps:get(tag, Meta, undefined)), Tag = maps:get(tag, ReportRaw, maps:get(tag, Meta, undefined)),
@ -99,6 +140,7 @@ enrich_report(ReportRaw, Meta) ->
{topic, try_format_unicode(Topic)}, {topic, try_format_unicode(Topic)},
{username, try_format_unicode(Username)}, {username, try_format_unicode(Username)},
{peername, Peer}, {peername, Peer},
{mfa, try_format_unicode(MFA)},
{msg, Msg}, {msg, Msg},
{clientid, try_format_unicode(ClientId)}, {clientid, try_format_unicode(ClientId)},
{tag, Tag} {tag, Tag}
@ -137,3 +179,29 @@ enrich_topic({Fmt, Args}, #{topic := Topic}) when is_list(Fmt) ->
{" topic: ~ts" ++ Fmt, [Topic | Args]}; {" topic: ~ts" ++ Fmt, [Topic | Args]};
enrich_topic(Msg, _) -> enrich_topic(Msg, _) ->
Msg. Msg.
try_encode_meta(Report, Config) ->
lists:foldl(
fun(Meta, Acc) ->
try_encode_meta(Meta, Acc, Config)
end,
Report,
[payload, packet]
).
try_encode_meta(payload, #{payload := Payload} = Report, #{payload_encode := Encode}) ->
Report#{payload := encode_payload(Payload, Encode)};
try_encode_meta(packet, #{packet := Packet} = Report, #{payload_encode := Encode}) when
is_tuple(Packet)
->
Report#{packet := emqx_packet:format(Packet, Encode)};
try_encode_meta(_, Report, _Config) ->
Report.
encode_payload(Payload, text) ->
Payload;
encode_payload(_Payload, hidden) ->
"******";
encode_payload(Payload, hex) ->
Bin = emqx_utils_conv:bin(Payload),
binary:encode_hex(Bin).

View File

@ -22,6 +22,7 @@
-include("logger.hrl"). -include("logger.hrl").
-include("types.hrl"). -include("types.hrl").
-include("emqx_mqtt.hrl"). -include("emqx_mqtt.hrl").
-include("emqx_metrics.hrl").
-export([ -export([
start_link/0, start_link/0,
@ -86,206 +87,8 @@
-define(TAB, ?MODULE). -define(TAB, ?MODULE).
-define(SERVER, ?MODULE). -define(SERVER, ?MODULE).
%% Bytes sent and received
-define(BYTES_METRICS,
% Total bytes received
[
{counter, 'bytes.received'},
% Total bytes sent
{counter, 'bytes.sent'}
]
).
%% Packets sent and received
-define(PACKET_METRICS,
% All Packets received
[
{counter, 'packets.received'},
% All Packets sent
{counter, 'packets.sent'},
% CONNECT Packets received
{counter, 'packets.connect.received'},
% CONNACK Packets sent
{counter, 'packets.connack.sent'},
% CONNACK error sent
{counter, 'packets.connack.error'},
% CONNACK auth_error sent
{counter, 'packets.connack.auth_error'},
% PUBLISH packets received
{counter, 'packets.publish.received'},
% PUBLISH packets sent
{counter, 'packets.publish.sent'},
% PUBLISH packet_id inuse
{counter, 'packets.publish.inuse'},
% PUBLISH failed for error
{counter, 'packets.publish.error'},
% PUBLISH failed for auth error
{counter, 'packets.publish.auth_error'},
% PUBLISH(QoS2) packets dropped
{counter, 'packets.publish.dropped'},
% PUBACK packets received
{counter, 'packets.puback.received'},
% PUBACK packets sent
{counter, 'packets.puback.sent'},
% PUBACK packet_id inuse
{counter, 'packets.puback.inuse'},
% PUBACK packets missed
{counter, 'packets.puback.missed'},
% PUBREC packets received
{counter, 'packets.pubrec.received'},
% PUBREC packets sent
{counter, 'packets.pubrec.sent'},
% PUBREC packet_id inuse
{counter, 'packets.pubrec.inuse'},
% PUBREC packets missed
{counter, 'packets.pubrec.missed'},
% PUBREL packets received
{counter, 'packets.pubrel.received'},
% PUBREL packets sent
{counter, 'packets.pubrel.sent'},
% PUBREL packets missed
{counter, 'packets.pubrel.missed'},
% PUBCOMP packets received
{counter, 'packets.pubcomp.received'},
% PUBCOMP packets sent
{counter, 'packets.pubcomp.sent'},
% PUBCOMP packet_id inuse
{counter, 'packets.pubcomp.inuse'},
% PUBCOMP packets missed
{counter, 'packets.pubcomp.missed'},
% SUBSCRIBE Packets received
{counter, 'packets.subscribe.received'},
% SUBSCRIBE error
{counter, 'packets.subscribe.error'},
% SUBSCRIBE failed for not auth
{counter, 'packets.subscribe.auth_error'},
% SUBACK packets sent
{counter, 'packets.suback.sent'},
% UNSUBSCRIBE Packets received
{counter, 'packets.unsubscribe.received'},
% UNSUBSCRIBE error
{counter, 'packets.unsubscribe.error'},
% UNSUBACK Packets sent
{counter, 'packets.unsuback.sent'},
% PINGREQ packets received
{counter, 'packets.pingreq.received'},
% PINGRESP Packets sent
{counter, 'packets.pingresp.sent'},
% DISCONNECT Packets received
{counter, 'packets.disconnect.received'},
% DISCONNECT Packets sent
{counter, 'packets.disconnect.sent'},
% Auth Packets received
{counter, 'packets.auth.received'},
% Auth Packets sent
{counter, 'packets.auth.sent'}
]
).
%% Messages sent/received and pubsub
-define(MESSAGE_METRICS,
% All Messages received
[
{counter, 'messages.received'},
% All Messages sent
{counter, 'messages.sent'},
% QoS0 Messages received
{counter, 'messages.qos0.received'},
% QoS0 Messages sent
{counter, 'messages.qos0.sent'},
% QoS1 Messages received
{counter, 'messages.qos1.received'},
% QoS1 Messages sent
{counter, 'messages.qos1.sent'},
% QoS2 Messages received
{counter, 'messages.qos2.received'},
% QoS2 Messages sent
{counter, 'messages.qos2.sent'},
%% PubSub Metrics
% Messages Publish
{counter, 'messages.publish'},
% Messages dropped due to no subscribers
{counter, 'messages.dropped'},
%% % Messages that failed validations
{counter, 'messages.validation_failed'},
%% % Messages that passed validations
{counter, 'messages.validation_succeeded'},
% QoS2 Messages expired
{counter, 'messages.dropped.await_pubrel_timeout'},
% Messages dropped
{counter, 'messages.dropped.no_subscribers'},
% Messages forward
{counter, 'messages.forward'},
% Messages delayed
{counter, 'messages.delayed'},
% Messages delivered
{counter, 'messages.delivered'},
% Messages acked
{counter, 'messages.acked'},
% Messages persistently stored
{counter, 'messages.persisted'}
]
).
%% Delivery metrics
-define(DELIVERY_METRICS, [
{counter, 'delivery.dropped'},
{counter, 'delivery.dropped.no_local'},
{counter, 'delivery.dropped.too_large'},
{counter, 'delivery.dropped.qos0_msg'},
{counter, 'delivery.dropped.queue_full'},
{counter, 'delivery.dropped.expired'}
]).
%% Client Lifecircle metrics
-define(CLIENT_METRICS, [
{counter, 'client.connect'},
{counter, 'client.connack'},
{counter, 'client.connected'},
{counter, 'client.authenticate'},
{counter, 'client.auth.anonymous'},
{counter, 'client.authorize'},
{counter, 'client.subscribe'},
{counter, 'client.unsubscribe'},
{counter, 'client.disconnected'}
]).
%% Session Lifecircle metrics
-define(SESSION_METRICS, [
{counter, 'session.created'},
{counter, 'session.resumed'},
{counter, 'session.takenover'},
{counter, 'session.discarded'},
{counter, 'session.terminated'}
]).
%% Statistic metrics for ACL checking
-define(STASTS_ACL_METRICS, [
{counter, 'authorization.allow'},
{counter, 'authorization.deny'},
{counter, 'authorization.cache_hit'},
{counter, 'authorization.cache_miss'}
]).
%% Statistic metrics for auth checking
-define(STASTS_AUTHN_METRICS, [
{counter, 'authentication.success'},
{counter, 'authentication.success.anonymous'},
{counter, 'authentication.failure'}
]).
%% Overload protection counters
-define(OLP_METRICS, [
{counter, 'overload_protection.delay.ok'},
{counter, 'overload_protection.delay.timeout'},
{counter, 'overload_protection.hibernation'},
{counter, 'overload_protection.gc'},
{counter, 'overload_protection.new_conn'}
]).
olp_metrics() -> olp_metrics() ->
lists:map(fun({_, Metric}) -> Metric end, ?OLP_METRICS). lists:map(fun({_, Metric, _}) -> Metric end, ?OLP_METRICS).
-record(state, {next_idx = 1}). -record(state, {next_idx = 1}).
@ -566,7 +369,7 @@ init([]) ->
]), ]),
% Store reserved indices % Store reserved indices
ok = lists:foreach( ok = lists:foreach(
fun({Type, Name}) -> fun({Type, Name, _Desc}) ->
Idx = reserved_idx(Name), Idx = reserved_idx(Name),
Metric = #metric{name = Name, type = Type, idx = Idx}, Metric = #metric{name = Name, type = Type, idx = Idx},
true = ets:insert(?TAB, Metric), true = ets:insert(?TAB, Metric),
@ -680,11 +483,11 @@ reserved_idx('messages.dropped') -> 109;
reserved_idx('messages.dropped.await_pubrel_timeout') -> 110; reserved_idx('messages.dropped.await_pubrel_timeout') -> 110;
reserved_idx('messages.dropped.no_subscribers') -> 111; reserved_idx('messages.dropped.no_subscribers') -> 111;
reserved_idx('messages.forward') -> 112; reserved_idx('messages.forward') -> 112;
%%reserved_idx('messages.retained') -> 113; %% keep the index, new metrics can use this %% reserved_idx('messages.retained') -> 113; %% keep the index, new metrics can use this
reserved_idx('messages.delayed') -> 114; reserved_idx('messages.delayed') -> 114;
reserved_idx('messages.delivered') -> 115; reserved_idx('messages.delivered') -> 115;
reserved_idx('messages.acked') -> 116; reserved_idx('messages.acked') -> 116;
reserved_idx('delivery.expired') -> 117; %% reserved_idx('delivery.expired') -> 117; %% have never used
reserved_idx('delivery.dropped') -> 118; reserved_idx('delivery.dropped') -> 118;
reserved_idx('delivery.dropped.no_local') -> 119; reserved_idx('delivery.dropped.no_local') -> 119;
reserved_idx('delivery.dropped.too_large') -> 120; reserved_idx('delivery.dropped.too_large') -> 120;
@ -695,7 +498,7 @@ reserved_idx('client.connect') -> 200;
reserved_idx('client.connack') -> 201; reserved_idx('client.connack') -> 201;
reserved_idx('client.connected') -> 202; reserved_idx('client.connected') -> 202;
reserved_idx('client.authenticate') -> 203; reserved_idx('client.authenticate') -> 203;
reserved_idx('client.enhanced_authenticate') -> 204; %% reserved_idx('client.enhanced_authenticate') -> 204; %% have never used
reserved_idx('client.auth.anonymous') -> 205; reserved_idx('client.auth.anonymous') -> 205;
reserved_idx('client.authorize') -> 206; reserved_idx('client.authorize') -> 206;
reserved_idx('client.subscribe') -> 207; reserved_idx('client.subscribe') -> 207;
@ -721,4 +524,6 @@ reserved_idx('overload_protection.new_conn') -> 404;
reserved_idx('messages.validation_succeeded') -> 405; reserved_idx('messages.validation_succeeded') -> 405;
reserved_idx('messages.validation_failed') -> 406; reserved_idx('messages.validation_failed') -> 406;
reserved_idx('messages.persisted') -> 407; reserved_idx('messages.persisted') -> 407;
reserved_idx('messages.transformation_succeeded') -> 408;
reserved_idx('messages.transformation_failed') -> 409;
reserved_idx(_) -> undefined. reserved_idx(_) -> undefined.

View File

@ -51,7 +51,6 @@
]). ]).
-export([ -export([
format/1,
format/2 format/2
]). ]).
@ -481,10 +480,6 @@ will_msg(#mqtt_packet_connect{
headers = #{username => Username, properties => Props} headers = #{username => Username, properties => Props}
}. }.
%% @doc Format packet
-spec format(emqx_types:packet()) -> iolist().
format(Packet) -> format(Packet, emqx_trace_handler:payload_encode()).
%% @doc Format packet %% @doc Format packet
-spec format(emqx_types:packet(), hex | text | hidden) -> iolist(). -spec format(emqx_types:packet(), hex | text | hidden) -> iolist().
format(#mqtt_packet{header = Header, variable = Variable, payload = Payload}, PayloadEncode) -> format(#mqtt_packet{header = Header, variable = Variable, payload = Payload}, PayloadEncode) ->

View File

@ -102,7 +102,11 @@ hash({SimpleHash, _Salt, disable}, Password) when is_binary(Password) ->
hash({SimpleHash, Salt, prefix}, Password) when is_binary(Password), is_binary(Salt) -> hash({SimpleHash, Salt, prefix}, Password) when is_binary(Password), is_binary(Salt) ->
hash_data(SimpleHash, <<Salt/binary, Password/binary>>); hash_data(SimpleHash, <<Salt/binary, Password/binary>>);
hash({SimpleHash, Salt, suffix}, Password) when is_binary(Password), is_binary(Salt) -> hash({SimpleHash, Salt, suffix}, Password) when is_binary(Password), is_binary(Salt) ->
hash_data(SimpleHash, <<Password/binary, Salt/binary>>). hash_data(SimpleHash, <<Password/binary, Salt/binary>>);
hash({_SimpleHash, Salt, _SaltPos}, _Password) when not is_binary(Salt) ->
error({salt_not_string, Salt});
hash({_SimpleHash, _Salt, _SaltPos}, Password) when not is_binary(Password) ->
error({password_not_string, Password}).
-spec hash_data(hash_type(), binary()) -> binary(). -spec hash_data(hash_type(), binary()) -> binary().
hash_data(plain, Data) when is_binary(Data) -> hash_data(plain, Data) when is_binary(Data) ->

View File

@ -32,15 +32,7 @@
persist/1 persist/1
]). ]).
-define(PERSISTENT_MESSAGE_DB, emqx_persistent_message). -include("emqx_persistent_message.hrl").
-define(PERSISTENCE_ENABLED, emqx_message_persistence_enabled).
-define(WHEN_ENABLED(DO),
case is_persistence_enabled() of
true -> DO;
false -> {skipped, disabled}
end
).
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
@ -51,7 +43,7 @@ init() ->
Zones = maps:keys(emqx_config:get([zones])), Zones = maps:keys(emqx_config:get([zones])),
IsEnabled = lists:any(fun is_persistence_enabled/1, Zones), IsEnabled = lists:any(fun is_persistence_enabled/1, Zones),
persistent_term:put(?PERSISTENCE_ENABLED, IsEnabled), persistent_term:put(?PERSISTENCE_ENABLED, IsEnabled),
?WHEN_ENABLED(begin ?WITH_DURABILITY_ENABLED(begin
?SLOG(notice, #{msg => "Session durability is enabled"}), ?SLOG(notice, #{msg => "Session durability is enabled"}),
Backend = storage_backend(), Backend = storage_backend(),
ok = emqx_ds:open_db(?PERSISTENT_MESSAGE_DB, Backend), ok = emqx_ds:open_db(?PERSISTENT_MESSAGE_DB, Backend),
@ -62,11 +54,11 @@ init() ->
-spec is_persistence_enabled() -> boolean(). -spec is_persistence_enabled() -> boolean().
is_persistence_enabled() -> is_persistence_enabled() ->
persistent_term:get(?PERSISTENCE_ENABLED). persistent_term:get(?PERSISTENCE_ENABLED, false).
-spec is_persistence_enabled(emqx_types:zone()) -> boolean(). -spec is_persistence_enabled(emqx_types:zone()) -> boolean().
is_persistence_enabled(Zone) -> is_persistence_enabled(Zone) ->
emqx_config:get_zone_conf(Zone, [session_persistence, enable]). emqx_config:get_zone_conf(Zone, [durable_sessions, enable]).
-spec storage_backend() -> emqx_ds:create_db_opts(). -spec storage_backend() -> emqx_ds:create_db_opts().
storage_backend() -> storage_backend() ->
@ -76,7 +68,7 @@ storage_backend() ->
%% `emqx_persistent_session_ds': %% `emqx_persistent_session_ds':
-spec force_ds(emqx_types:zone()) -> boolean(). -spec force_ds(emqx_types:zone()) -> boolean().
force_ds(Zone) -> force_ds(Zone) ->
emqx_config:get_zone_conf(Zone, [session_persistence, force_persistence]). emqx_config:get_zone_conf(Zone, [durable_sessions, force_persistence]).
storage_backend(Path) -> storage_backend(Path) ->
ConfigTree = #{'_config_handler' := {Module, Function}} = emqx_config:get(Path), ConfigTree = #{'_config_handler' := {Module, Function}} = emqx_config:get(Path),
@ -86,12 +78,12 @@ storage_backend(Path) ->
-spec add_handler() -> ok. -spec add_handler() -> ok.
add_handler() -> add_handler() ->
emqx_config_handler:add_handler([session_persistence], ?MODULE). emqx_config_handler:add_handler([durable_sessions], ?MODULE).
pre_config_update([session_persistence], #{<<"enable">> := New}, #{<<"enable">> := Old}) when pre_config_update([durable_sessions], #{<<"enable">> := New}, #{<<"enable">> := Old}) when
New =/= Old New =/= Old
-> ->
{error, "Hot update of session_persistence.enable parameter is currently not supported"}; {error, "Hot update of durable_sessions.enable parameter is currently not supported"};
pre_config_update(_Root, _NewConf, _OldConf) -> pre_config_update(_Root, _NewConf, _OldConf) ->
ok. ok.
@ -100,7 +92,7 @@ pre_config_update(_Root, _NewConf, _OldConf) ->
-spec persist(emqx_types:message()) -> -spec persist(emqx_types:message()) ->
emqx_ds:store_batch_result() | {skipped, needs_no_persistence}. emqx_ds:store_batch_result() | {skipped, needs_no_persistence}.
persist(Msg) -> persist(Msg) ->
?WHEN_ENABLED( ?WITH_DURABILITY_ENABLED(
case needs_persistence(Msg) andalso has_subscribers(Msg) of case needs_persistence(Msg) andalso has_subscribers(Msg) of
true -> true ->
store_message(Msg); store_message(Msg);
@ -110,7 +102,7 @@ persist(Msg) ->
). ).
needs_persistence(Msg) -> needs_persistence(Msg) ->
not (emqx_message:get_flag(dup, Msg) orelse emqx_message:is_sys(Msg)). not emqx_message:get_flag(dup, Msg).
-spec store_message(emqx_types:message()) -> emqx_ds:store_batch_result(). -spec store_message(emqx_types:message()) -> emqx_ds:store_batch_result().
store_message(Msg) -> store_message(Msg) ->

View File

@ -25,7 +25,8 @@
-include("emqx_mqtt.hrl"). -include("emqx_mqtt.hrl").
-include("emqx_persistent_session_ds.hrl"). -include("emqx_session.hrl").
-include("emqx_persistent_session_ds/session_internals.hrl").
-ifdef(TEST). -ifdef(TEST).
-include_lib("proper/include/proper.hrl"). -include_lib("proper/include/proper.hrl").
@ -63,6 +64,7 @@
deliver/3, deliver/3,
replay/3, replay/3,
handle_timeout/3, handle_timeout/3,
handle_info/2,
disconnect/2, disconnect/2,
terminate/2 terminate/2
]). ]).
@ -106,6 +108,7 @@
seqno/0, seqno/0,
timestamp/0, timestamp/0,
topic_filter/0, topic_filter/0,
share_topic_filter/0,
subscription_id/0, subscription_id/0,
subscription/0, subscription/0,
session/0, session/0,
@ -117,7 +120,8 @@
%% Currently, this is the clientid. We avoid `emqx_types:clientid()' because that can be %% Currently, this is the clientid. We avoid `emqx_types:clientid()' because that can be
%% an atom, in theory (?). %% an atom, in theory (?).
-type id() :: binary(). -type id() :: binary().
-type topic_filter() :: emqx_types:topic() | #share{}. -type share_topic_filter() :: #share{}.
-type topic_filter() :: emqx_types:topic() | share_topic_filter().
%% Subscription and subscription states: %% Subscription and subscription states:
%% %%
@ -155,6 +159,8 @@
subopts := map() subopts := map()
}. }.
-type shared_sub_state() :: term().
-define(TIMER_PULL, timer_pull). -define(TIMER_PULL, timer_pull).
-define(TIMER_GET_STREAMS, timer_get_streams). -define(TIMER_GET_STREAMS, timer_get_streams).
-define(TIMER_BUMP_LAST_ALIVE_AT, timer_bump_last_alive_at). -define(TIMER_BUMP_LAST_ALIVE_AT, timer_bump_last_alive_at).
@ -172,8 +178,13 @@
props := map(), props := map(),
%% Persistent state: %% Persistent state:
s := emqx_persistent_session_ds_state:t(), s := emqx_persistent_session_ds_state:t(),
%% Shared subscription state:
shared_sub_s := shared_sub_state(),
%% Buffer: %% Buffer:
inflight := emqx_persistent_session_ds_inflight:t(), inflight := emqx_persistent_session_ds_inflight:t(),
%% Last fetched stream:
%% Used as a continuation point for fair stream scheduling.
last_fetched_stream => emqx_persistent_session_ds_state:stream_key(),
%% In-progress replay: %% In-progress replay:
%% List of stream replay states to be added to the inflight buffer. %% List of stream replay states to be added to the inflight buffer.
replay => [{_StreamKey, stream_state()}, ...], replay => [{_StreamKey, stream_state()}, ...],
@ -277,8 +288,11 @@ info(created_at, #{s := S}) ->
emqx_persistent_session_ds_state:get_created_at(S); emqx_persistent_session_ds_state:get_created_at(S);
info(is_persistent, #{}) -> info(is_persistent, #{}) ->
true; true;
info(subscriptions, #{s := S}) -> info(subscriptions, #{s := S, shared_sub_s := SharedSubS}) ->
emqx_persistent_session_ds_subs:to_map(S); maps:merge(
emqx_persistent_session_ds_subs:to_map(S),
emqx_persistent_session_ds_shared_subs:to_map(S, SharedSubS)
);
info(subscriptions_cnt, #{s := S}) -> info(subscriptions_cnt, #{s := S}) ->
emqx_persistent_session_ds_state:n_subscriptions(S); emqx_persistent_session_ds_state:n_subscriptions(S);
info(subscriptions_max, #{props := Conf}) -> info(subscriptions_max, #{props := Conf}) ->
@ -356,15 +370,23 @@ print_session(ClientId) ->
%% Client -> Broker: SUBSCRIBE / UNSUBSCRIBE %% Client -> Broker: SUBSCRIBE / UNSUBSCRIBE
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Suppress warnings about clauses handling unimplemented results
%% of `emqx_persistent_session_ds_shared_subs:on_subscribe/3`
-dialyzer({nowarn_function, subscribe/3}).
-spec subscribe(topic_filter(), emqx_types:subopts(), session()) -> -spec subscribe(topic_filter(), emqx_types:subopts(), session()) ->
{ok, session()} | {error, emqx_types:reason_code()}. {ok, session()} | {error, emqx_types:reason_code()}.
subscribe( subscribe(
#share{}, #share{} = TopicFilter,
_SubOpts, SubOpts,
_Session Session
) -> ) ->
%% TODO: Shared subscriptions are not supported yet: case emqx_persistent_session_ds_shared_subs:on_subscribe(TopicFilter, SubOpts, Session) of
{error, ?RC_SHARED_SUBSCRIPTIONS_NOT_SUPPORTED}; {ok, S0, SharedSubS} ->
S = emqx_persistent_session_ds_state:commit(S0),
{ok, Session#{s => S, shared_sub_s => SharedSubS}};
Error = {error, _} ->
Error
end;
subscribe( subscribe(
TopicFilter, TopicFilter,
SubOpts, SubOpts,
@ -378,8 +400,27 @@ subscribe(
Error Error
end. end.
%% Suppress warnings about clauses handling unimplemented results
%% of `emqx_persistent_session_ds_shared_subs:on_unsubscribe/4`
-dialyzer({nowarn_function, unsubscribe/2}).
-spec unsubscribe(topic_filter(), session()) -> -spec unsubscribe(topic_filter(), session()) ->
{ok, session(), emqx_types:subopts()} | {error, emqx_types:reason_code()}. {ok, session(), emqx_types:subopts()} | {error, emqx_types:reason_code()}.
unsubscribe(
#share{} = TopicFilter,
Session = #{id := SessionId, s := S0, shared_sub_s := SharedSubS0}
) ->
case
emqx_persistent_session_ds_shared_subs:on_unsubscribe(
SessionId, TopicFilter, S0, SharedSubS0
)
of
{ok, S1, SharedSubS1, #{id := SubId, subopts := SubOpts}} ->
S2 = emqx_persistent_session_ds_stream_scheduler:on_unsubscribe(SubId, S1),
S = emqx_persistent_session_ds_state:commit(S2),
{ok, Session#{s => S, shared_sub_s => SharedSubS1}, SubOpts};
Error = {error, _} ->
Error
end;
unsubscribe( unsubscribe(
TopicFilter, TopicFilter,
Session = #{id := SessionId, s := S0} Session = #{id := SessionId, s := S0}
@ -540,6 +581,8 @@ pubcomp(_ClientInfo, PacketId, Session0) ->
end. end.
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Delivers
%%--------------------------------------------------------------------
-spec deliver(clientinfo(), [emqx_types:deliver()], session()) -> -spec deliver(clientinfo(), [emqx_types:deliver()], session()) ->
{ok, replies(), session()}. {ok, replies(), session()}.
@ -551,6 +594,10 @@ deliver(ClientInfo, Delivers, Session0) ->
), ),
{ok, [], pull_now(Session)}. {ok, [], pull_now(Session)}.
%%--------------------------------------------------------------------
%% Timeouts
%%--------------------------------------------------------------------
-spec handle_timeout(clientinfo(), _Timeout, session()) -> -spec handle_timeout(clientinfo(), _Timeout, session()) ->
{ok, replies(), session()} | {ok, replies(), timeout(), session()}. {ok, replies(), session()} | {ok, replies(), timeout(), session()}.
handle_timeout(ClientInfo, ?TIMER_PULL, Session0) -> handle_timeout(ClientInfo, ?TIMER_PULL, Session0) ->
@ -573,14 +620,19 @@ handle_timeout(ClientInfo, ?TIMER_PULL, Session0) ->
handle_timeout(ClientInfo, ?TIMER_RETRY_REPLAY, Session0) -> handle_timeout(ClientInfo, ?TIMER_RETRY_REPLAY, Session0) ->
Session = replay_streams(Session0, ClientInfo), Session = replay_streams(Session0, ClientInfo),
{ok, [], Session}; {ok, [], Session};
handle_timeout(ClientInfo, ?TIMER_GET_STREAMS, Session0 = #{s := S0}) -> handle_timeout(ClientInfo, ?TIMER_GET_STREAMS, Session0 = #{s := S0, shared_sub_s := SharedSubS0}) ->
S1 = emqx_persistent_session_ds_subs:gc(S0), %% `gc` and `renew_streams` methods may drop unsubscribed streams.
S = emqx_persistent_session_ds_stream_scheduler:renew_streams(S1), %% Shared subscription handler must have a chance to see unsubscribed streams
%% in the fully replayed state.
{S1, SharedSubS1} = emqx_persistent_session_ds_shared_subs:pre_renew_streams(S0, SharedSubS0),
S2 = emqx_persistent_session_ds_subs:gc(S1),
S3 = emqx_persistent_session_ds_stream_scheduler:renew_streams(S2),
{S, SharedSubS} = emqx_persistent_session_ds_shared_subs:renew_streams(S3, SharedSubS1),
Interval = get_config(ClientInfo, [renew_streams_interval]), Interval = get_config(ClientInfo, [renew_streams_interval]),
Session = emqx_session:ensure_timer( Session = emqx_session:ensure_timer(
?TIMER_GET_STREAMS, ?TIMER_GET_STREAMS,
Interval, Interval,
Session0#{s => S} Session0#{s => S, shared_sub_s => SharedSubS}
), ),
{ok, [], Session}; {ok, [], Session};
handle_timeout(_ClientInfo, ?TIMER_BUMP_LAST_ALIVE_AT, Session0 = #{s := S0}) -> handle_timeout(_ClientInfo, ?TIMER_BUMP_LAST_ALIVE_AT, Session0 = #{s := S0}) ->
@ -601,6 +653,22 @@ handle_timeout(_ClientInfo, Timeout, Session) ->
?SLOG(warning, #{msg => "unknown_ds_timeout", timeout => Timeout}), ?SLOG(warning, #{msg => "unknown_ds_timeout", timeout => Timeout}),
{ok, [], Session}. {ok, [], Session}.
%%--------------------------------------------------------------------
%% Generic messages
%%--------------------------------------------------------------------
-spec handle_info(term(), session()) -> session().
handle_info(?shared_sub_message(Msg), Session = #{s := S0, shared_sub_s := SharedSubS0}) ->
{S, SharedSubS} = emqx_persistent_session_ds_shared_subs:on_info(S0, SharedSubS0, Msg),
Session#{s => S, shared_sub_s => SharedSubS}.
%%--------------------------------------------------------------------
%% Shared subscription outgoing messages
%%--------------------------------------------------------------------
shared_sub_opts(SessionId) ->
#{session_id => SessionId}.
bump_last_alive(S0) -> bump_last_alive(S0) ->
%% Note: we take a pessimistic approach here and assume that the client will be alive %% 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 %% until the next bump timeout. With this, we avoid garbage collecting this session
@ -622,15 +690,17 @@ replay_streams(Session0 = #{replay := [{StreamKey, Srs0} | Rest]}, ClientInfo) -
replay_streams(Session#{replay := Rest}, ClientInfo); replay_streams(Session#{replay := Rest}, ClientInfo);
{error, recoverable, Reason} -> {error, recoverable, Reason} ->
RetryTimeout = ?TIMEOUT_RETRY_REPLAY, RetryTimeout = ?TIMEOUT_RETRY_REPLAY,
?SLOG(warning, #{ ?SLOG(debug, #{
msg => "failed_to_fetch_replay_batch", msg => "failed_to_fetch_replay_batch",
stream => StreamKey, stream => StreamKey,
reason => Reason, reason => Reason,
class => recoverable, class => recoverable,
retry_in_ms => RetryTimeout retry_in_ms => RetryTimeout
}), }),
emqx_session:ensure_timer(?TIMER_RETRY_REPLAY, RetryTimeout, Session0) emqx_session:ensure_timer(?TIMER_RETRY_REPLAY, RetryTimeout, Session0);
%% TODO: Handle unrecoverable errors. {error, unrecoverable, Reason} ->
Session1 = skip_batch(StreamKey, Srs0, Session0, ClientInfo, Reason),
replay_streams(Session1#{replay := Rest}, ClientInfo)
end; end;
replay_streams(Session0 = #{replay := []}, _ClientInfo) -> replay_streams(Session0 = #{replay := []}, _ClientInfo) ->
Session = maps:remove(replay, Session0), Session = maps:remove(replay, Session0),
@ -655,20 +725,55 @@ replay_batch(Srs0, Session0, ClientInfo) ->
Error Error
end. end.
%% Handle `{error, unrecoverable, _}' returned by `enqueue_batch'.
%% Most likely they mean that the generation containing the messages
%% has been removed.
-spec skip_batch(_StreamKey, stream_state(), session(), clientinfo(), _Reason) -> session().
skip_batch(StreamKey, SRS0, Session = #{s := S0}, ClientInfo, Reason) ->
?SLOG(info, #{
msg => "session_ds_replay_unrecoverable_error",
reason => Reason,
srs => SRS0
}),
GenEvents = fun
F(QoS, SeqNo, LastSeqNo) when SeqNo < LastSeqNo ->
FakeMsg = #message{
id = <<>>,
qos = QoS,
payload = <<>>,
topic = <<>>,
timestamp = 0
},
_ = emqx_session_events:handle_event(ClientInfo, {expired, FakeMsg}),
F(QoS, inc_seqno(QoS, SeqNo), LastSeqNo);
F(_, _, _) ->
ok
end,
%% Treat messages as expired:
GenEvents(?QOS_1, SRS0#srs.first_seqno_qos1, SRS0#srs.last_seqno_qos1),
GenEvents(?QOS_2, SRS0#srs.first_seqno_qos2, SRS0#srs.last_seqno_qos2),
SRS = SRS0#srs{it_end = end_of_stream, batch_size = 0},
%% That's it for the iterator. Mark SRS as reached the
%% `end_of_stream', and let stream scheduler do the rest:
S = emqx_persistent_session_ds_state:put_stream(StreamKey, SRS, S0),
Session#{s := S}.
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
-spec disconnect(session(), emqx_types:conninfo()) -> {shutdown, session()}. -spec disconnect(session(), emqx_types:conninfo()) -> {shutdown, session()}.
disconnect(Session = #{s := S0}, ConnInfo) -> disconnect(Session = #{id := Id, s := S0, shared_sub_s := SharedSubS0}, ConnInfo) ->
S1 = emqx_persistent_session_ds_state:set_last_alive_at(now_ms(), S0), S1 = maybe_set_offline_info(S0, Id),
S2 = S2 = emqx_persistent_session_ds_state:set_last_alive_at(now_ms(), S1),
S3 =
case ConnInfo of case ConnInfo of
#{expiry_interval := EI} when is_number(EI) -> #{expiry_interval := EI} when is_number(EI) ->
emqx_persistent_session_ds_state:set_expiry_interval(EI, S1); emqx_persistent_session_ds_state:set_expiry_interval(EI, S2);
_ -> _ ->
S1 S2
end, end,
S = emqx_persistent_session_ds_state:commit(S2), {S4, SharedSubS} = emqx_persistent_session_ds_shared_subs:on_disconnect(S3, SharedSubS0),
{shutdown, Session#{s => S}}. S = emqx_persistent_session_ds_state:commit(S4),
{shutdown, Session#{s => S, shared_sub_s => SharedSubS}}.
-spec terminate(Reason :: term(), session()) -> ok. -spec terminate(Reason :: term(), session()) -> ok.
terminate(_Reason, Session = #{id := Id, s := S}) -> terminate(_Reason, Session = #{id := Id, s := S}) ->
@ -702,7 +807,7 @@ list_client_subscriptions(ClientId) ->
maps:fold( maps:fold(
fun(Topic, #{current_state := CS}, Acc) -> fun(Topic, #{current_state := CS}, Acc) ->
#{subopts := SubOpts} = maps:get(CS, SStates), #{subopts := SubOpts} = maps:get(CS, SStates),
Elem = {Topic, SubOpts}, Elem = {Topic, SubOpts#{durable => true}},
[Elem | Acc] [Elem | Acc]
end, end,
[], [],
@ -716,10 +821,12 @@ list_client_subscriptions(ClientId) ->
{error, not_found} {error, not_found}
end. end.
-spec get_client_subscription(emqx_types:clientid(), emqx_types:topic()) -> -spec get_client_subscription(emqx_types:clientid(), topic_filter() | share_topic_filter()) ->
subscription() | undefined. subscription() | undefined.
get_client_subscription(ClientId, Topic) -> get_client_subscription(ClientId, #share{} = ShareTopicFilter) ->
emqx_persistent_session_ds_subs:cold_get_subscription(ClientId, Topic). emqx_persistent_session_ds_shared_subs:cold_get_subscription(ClientId, ShareTopicFilter);
get_client_subscription(ClientId, TopicFilter) ->
emqx_persistent_session_ds_subs:cold_get_subscription(ClientId, TopicFilter).
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Session tables operations %% Session tables operations
@ -778,13 +885,17 @@ session_open(
S4 = emqx_persistent_session_ds_state:set_will_message(MaybeWillMsg, S3), S4 = emqx_persistent_session_ds_state:set_will_message(MaybeWillMsg, S3),
S5 = set_clientinfo(ClientInfo, S4), S5 = set_clientinfo(ClientInfo, S4),
S6 = emqx_persistent_session_ds_state:set_protocol({ProtoName, ProtoVer}, S5), S6 = emqx_persistent_session_ds_state:set_protocol({ProtoName, ProtoVer}, S5),
S = emqx_persistent_session_ds_state:commit(S6), {ok, S7, SharedSubS} = emqx_persistent_session_ds_shared_subs:open(
S6, shared_sub_opts(SessionId)
),
S = emqx_persistent_session_ds_state:commit(S7),
Inflight = emqx_persistent_session_ds_inflight:new( Inflight = emqx_persistent_session_ds_inflight:new(
receive_maximum(NewConnInfo) receive_maximum(NewConnInfo)
), ),
#{ #{
id => SessionId, id => SessionId,
s => S, s => S,
shared_sub_s => SharedSubS,
inflight => Inflight, inflight => Inflight,
props => #{} props => #{}
} }
@ -833,6 +944,7 @@ session_ensure_new(
id => Id, id => Id,
props => Conf, props => Conf,
s => S, s => S,
shared_sub_s => emqx_persistent_session_ds_shared_subs:new(shared_sub_opts(Id)),
inflight => emqx_persistent_session_ds_inflight:new(receive_maximum(ConnInfo)) inflight => emqx_persistent_session_ds_inflight:new(receive_maximum(ConnInfo))
}. }.
@ -843,8 +955,8 @@ session_drop(SessionId, Reason) ->
case emqx_persistent_session_ds_state:open(SessionId) of case emqx_persistent_session_ds_state:open(SessionId) of
{ok, S0} -> {ok, S0} ->
?tp(debug, drop_persistent_session, #{client_id => SessionId, reason => Reason}), ?tp(debug, drop_persistent_session, #{client_id => SessionId, reason => Reason}),
emqx_persistent_session_ds_subs:on_session_drop(SessionId, S0), ok = emqx_persistent_session_ds_subs:on_session_drop(SessionId, S0),
emqx_persistent_session_ds_state:delete(SessionId); ok = emqx_persistent_session_ds_state:delete(SessionId);
undefined -> undefined ->
ok ok
end. end.
@ -881,24 +993,33 @@ do_ensure_all_iterators_closed(_DSSessionID) ->
%% Normal replay: %% Normal replay:
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
fetch_new_messages(Session = #{s := S}, ClientInfo) -> fetch_new_messages(Session0 = #{s := S0, shared_sub_s := SharedSubS0}, ClientInfo) ->
Streams = emqx_persistent_session_ds_stream_scheduler:find_new_streams(S), {S1, SharedSubS1} = emqx_persistent_session_ds_shared_subs:on_streams_replay(S0, SharedSubS0),
fetch_new_messages(Streams, Session, ClientInfo). Session1 = Session0#{s => S1, shared_sub_s => SharedSubS1},
LFS = maps:get(last_fetched_stream, Session1, beginning),
fetch_new_messages([], Session, _ClientInfo) -> ItStream = emqx_persistent_session_ds_stream_scheduler:iter_next_streams(LFS, S1),
Session;
fetch_new_messages([I | Streams], Session0 = #{inflight := Inflight}, ClientInfo) ->
BatchSize = get_config(ClientInfo, [batch_size]), BatchSize = get_config(ClientInfo, [batch_size]),
Session2 = fetch_new_messages(ItStream, BatchSize, Session1, ClientInfo),
Session2#{shared_sub_s => SharedSubS1}.
fetch_new_messages(ItStream0, BatchSize, Session0, ClientInfo) ->
#{inflight := Inflight} = Session0,
case emqx_persistent_session_ds_inflight:n_buffered(all, Inflight) >= BatchSize of case emqx_persistent_session_ds_inflight:n_buffered(all, Inflight) >= BatchSize of
true -> true ->
%% Buffer is full: %% Buffer is full:
Session0; Session0;
false -> false ->
Session = new_batch(I, BatchSize, Session0, ClientInfo), case emqx_persistent_session_ds_stream_scheduler:next_stream(ItStream0) of
fetch_new_messages(Streams, Session, ClientInfo) {StreamKey, Srs, ItStream} ->
Session1 = new_batch(StreamKey, Srs, BatchSize, Session0, ClientInfo),
Session = Session1#{last_fetched_stream => StreamKey},
fetch_new_messages(ItStream, BatchSize, Session, ClientInfo);
none ->
Session0
end
end. end.
new_batch({StreamKey, Srs0}, BatchSize, Session0 = #{s := S0}, ClientInfo) -> new_batch(StreamKey, Srs0, BatchSize, Session0 = #{s := S0}, ClientInfo) ->
SN1 = emqx_persistent_session_ds_state:get_seqno(?next(?QOS_1), S0), SN1 = emqx_persistent_session_ds_state:get_seqno(?next(?QOS_1), S0),
SN2 = emqx_persistent_session_ds_state:get_seqno(?next(?QOS_2), S0), SN2 = emqx_persistent_session_ds_state:get_seqno(?next(?QOS_2), S0),
Srs1 = Srs0#srs{ Srs1 = Srs0#srs{
@ -922,15 +1043,16 @@ new_batch({StreamKey, Srs0}, BatchSize, Session0 = #{s := S0}, ClientInfo) ->
), ),
S = emqx_persistent_session_ds_state:put_stream(StreamKey, Srs, S2), S = emqx_persistent_session_ds_state:put_stream(StreamKey, Srs, S2),
Session#{s => S}; Session#{s => S};
{error, Class, Reason} -> {error, recoverable, Reason} ->
%% TODO: Handle unrecoverable error. ?SLOG(debug, #{
?SLOG(info, #{
msg => "failed_to_fetch_batch", msg => "failed_to_fetch_batch",
stream => StreamKey, stream => StreamKey,
reason => Reason, reason => Reason,
class => Class class => recoverable
}), }),
Session0 Session0;
{error, unrecoverable, Reason} ->
skip_batch(StreamKey, Srs1, Session0, ClientInfo, Reason)
end. end.
enqueue_batch(IsReplay, BatchSize, Srs0, Session = #{inflight := Inflight0, s := S}, ClientInfo) -> enqueue_batch(IsReplay, BatchSize, Srs0, Session = #{inflight := Inflight0, s := S}, ClientInfo) ->
@ -1145,14 +1267,14 @@ receive_maximum(ConnInfo) ->
expiry_interval(ConnInfo) -> expiry_interval(ConnInfo) ->
maps:get(expiry_interval, ConnInfo, 0). maps:get(expiry_interval, ConnInfo, 0).
%% Note: we don't allow overriding `last_alive_update_interval' per %% Note: we don't allow overriding `heartbeat_interval' per
%% zone, since the GC process is responsible for all sessions %% zone, since the GC process is responsible for all sessions
%% regardless of the zone. %% regardless of the zone.
bump_interval() -> bump_interval() ->
emqx_config:get([session_persistence, last_alive_update_interval]). emqx_config:get([durable_sessions, heartbeat_interval]).
get_config(#{zone := Zone}, Key) -> get_config(#{zone := Zone}, Key) ->
emqx_config:get_zone_conf(Zone, [session_persistence | Key]). emqx_config:get_zone_conf(Zone, [durable_sessions | Key]).
-spec try_get_live_session(emqx_types:clientid()) -> -spec try_get_live_session(emqx_types:clientid()) ->
{pid(), session()} | not_found | not_persistent. {pid(), session()} | not_found | not_persistent.
@ -1175,6 +1297,24 @@ try_get_live_session(ClientId) ->
not_found not_found
end. end.
-spec maybe_set_offline_info(emqx_persistent_session_ds_state:t(), emqx_types:clientid()) ->
emqx_persistent_session_ds_state:t().
maybe_set_offline_info(S, Id) ->
case emqx_cm:lookup_client({clientid, Id}) of
[{_Key, ChannelInfo, Stats}] ->
emqx_persistent_session_ds_state:set_offline_info(
#{
chan_info => ChannelInfo,
stats => Stats,
disconnected_at => erlang:system_time(millisecond),
last_connected_to => node()
},
S
);
_ ->
S
end.
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% SeqNo tracking %% SeqNo tracking
%% -------------------------------------------------------------------- %% --------------------------------------------------------------------

View File

@ -21,7 +21,7 @@
-include_lib("stdlib/include/qlc.hrl"). -include_lib("stdlib/include/qlc.hrl").
-include_lib("stdlib/include/ms_transform.hrl"). -include_lib("stdlib/include/ms_transform.hrl").
-include("emqx_persistent_session_ds.hrl"). -include("session_internals.hrl").
%% API %% API
-export([ -export([
@ -81,7 +81,7 @@ handle_info(_Info, State) ->
%%-------------------------------------------------------------------------------- %%--------------------------------------------------------------------------------
ensure_gc_timer() -> ensure_gc_timer() ->
Timeout = emqx_config:get([session_persistence, message_retention_period]), Timeout = emqx_config:get([durable_sessions, message_retention_period]),
_ = erlang:send_after(Timeout, self(), #gc{}), _ = erlang:send_after(Timeout, self(), #gc{}),
ok. ok.
@ -114,7 +114,7 @@ now_ms() ->
maybe_gc() -> maybe_gc() ->
AllGens = emqx_ds:list_generations_with_lifetimes(?PERSISTENT_MESSAGE_DB), AllGens = emqx_ds:list_generations_with_lifetimes(?PERSISTENT_MESSAGE_DB),
NowMS = now_ms(), NowMS = now_ms(),
RetentionPeriod = emqx_config:get([session_persistence, message_retention_period]), RetentionPeriod = emqx_config:get([durable_sessions, message_retention_period]),
TimeThreshold = NowMS - RetentionPeriod, TimeThreshold = NowMS - RetentionPeriod,
maybe_create_new_generation(AllGens, TimeThreshold), maybe_create_new_generation(AllGens, TimeThreshold),
?tp_span( ?tp_span(

View File

@ -0,0 +1,165 @@
%%--------------------------------------------------------------------
%% Copyright (c) 2024 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_persistent_session_bookkeeper).
-behaviour(gen_server).
%% API
-export([
start_link/0,
get_subscription_count/0,
get_disconnected_session_count/0
]).
%% `gen_server' API
-export([
init/1,
handle_continue/2,
handle_call/3,
handle_cast/2,
handle_info/2
]).
%%------------------------------------------------------------------------------
%% Type declarations
%%------------------------------------------------------------------------------
%% call/cast/info events
-record(tally_subs, {}).
-record(tally_disconnected_sessions, {}).
-record(get_subscription_count, {}).
-record(get_disconnected_session_count, {}).
%%------------------------------------------------------------------------------
%% API
%%------------------------------------------------------------------------------
-spec start_link() -> gen_server:start_ret().
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, _InitOpts = #{}, _Opts = []).
%% @doc Gets a cached view of the cluster-global count of persistent subscriptions.
-spec get_subscription_count() -> non_neg_integer().
get_subscription_count() ->
case emqx_persistent_message:is_persistence_enabled() of
true ->
gen_server:call(?MODULE, #get_subscription_count{}, infinity);
false ->
0
end.
%% @doc Gets a cached view of the cluster-global count of disconnected persistent sessions.
-spec get_disconnected_session_count() -> non_neg_integer().
get_disconnected_session_count() ->
case emqx_persistent_message:is_persistence_enabled() of
true ->
gen_server:call(?MODULE, #get_disconnected_session_count{}, infinity);
false ->
0
end.
%%------------------------------------------------------------------------------
%% `gen_server' API
%%------------------------------------------------------------------------------
init(_Opts) ->
case emqx_persistent_message:is_persistence_enabled() of
true ->
State = #{
subs_count => 0,
disconnected_session_count => 0
},
{ok, State, {continue, #tally_subs{}}};
false ->
ignore
end.
handle_continue(#tally_subs{}, State0) ->
State = tally_persistent_subscriptions(State0),
ensure_subs_tally_timer(),
{noreply, State, {continue, #tally_disconnected_sessions{}}};
handle_continue(#tally_disconnected_sessions{}, State0) ->
State = tally_disconnected_persistent_sessions(State0),
ensure_disconnected_sessions_tally_timer(),
{noreply, State}.
handle_call(#get_subscription_count{}, _From, State) ->
#{subs_count := N} = State,
{reply, N, State};
handle_call(#get_disconnected_session_count{}, _From, State) ->
#{disconnected_session_count := N} = State,
{reply, N, State};
handle_call(_Call, _From, State) ->
{reply, {error, bad_call}, State}.
handle_cast(_Cast, State) ->
{noreply, State}.
handle_info(#tally_subs{}, State0) ->
State = tally_persistent_subscriptions(State0),
ensure_subs_tally_timer(),
{noreply, State};
handle_info(#tally_disconnected_sessions{}, State0) ->
State = tally_disconnected_persistent_sessions(State0),
ensure_disconnected_sessions_tally_timer(),
{noreply, State};
handle_info(_Info, State) ->
{noreply, State}.
%%------------------------------------------------------------------------------
%% Internal fns
%%------------------------------------------------------------------------------
tally_persistent_subscriptions(State0) ->
N = emqx_persistent_session_ds_state:total_subscription_count(),
State0#{subs_count := N}.
tally_disconnected_persistent_sessions(State0) ->
N = do_tally_disconnected_persistent_sessions(),
State0#{disconnected_session_count := N}.
ensure_subs_tally_timer() ->
Timeout = emqx_config:get([durable_sessions, subscription_count_refresh_interval]),
_ = erlang:send_after(Timeout, self(), #tally_subs{}),
ok.
ensure_disconnected_sessions_tally_timer() ->
Timeout = emqx_config:get([durable_sessions, disconnected_session_count_refresh_interval]),
_ = erlang:send_after(Timeout, self(), #tally_disconnected_sessions{}),
ok.
do_tally_disconnected_persistent_sessions() ->
Iter = emqx_persistent_session_ds_state:make_session_iterator(),
do_tally_disconnected_persistent_sessions(Iter, 0).
do_tally_disconnected_persistent_sessions('$end_of_table', N) ->
N;
do_tally_disconnected_persistent_sessions(Iter0, N) ->
case emqx_persistent_session_ds_state:session_iterator_next(Iter0, 1) of
{[], _} ->
N;
{[{Id, _Meta}], Iter} ->
case is_live_session(Id) of
true ->
do_tally_disconnected_persistent_sessions(Iter, N);
false ->
do_tally_disconnected_persistent_sessions(Iter, N + 1)
end
end.
is_live_session(Id) ->
[] =/= emqx_cm_registry:lookup_channels(Id).

Some files were not shown because too many files have changed in this diff Show More