Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mqtt: Don't enqueue QoS>0 messages when publish in !MQTT_STATE_CONNEC… (IDFGH-4272) #177

Closed

Conversation

AxelLin
Copy link
Contributor

@AxelLin AxelLin commented Nov 11, 2020

…TED state

Enqueue QoS>0 messages in !MQTT_STATE_CONNECTED state may take too much outbox memory
before reaching OUTBOX_EXPIRED_TIMEOUT_MS. The ESP32 has limited memory, a task keep
publishing in a busy loop during offline can easily make device run into OOM.
Just make it return error if publish in wrong state no matter which QoS is used.
With this change now esp_mqtt_client_publish returns -1 for QoS>0 when offline,
this way the caller knows the publish failed.

Signed-off-by: Axel Lin axel.lin@ingics.com

…TED state

Enqueue QoS>0 messages in !MQTT_STATE_CONNECTED state may take too much outbox memory
before reaching OUTBOX_EXPIRED_TIMEOUT_MS. The ESP32 has limited memory, a task keep
publishing in a busy loop during offline can easily make device run into OOM.
Just make it return error if publish in wrong state no matter which QoS is used.
With this change now esp_mqtt_client_publish returns -1 for QoS>0 when offline,
this way the caller knows the publish failed.

Signed-off-by: Axel Lin <axel.lin@ingics.com>
@david-cermak
Copy link
Collaborator

Agree that this seems like a useful change for some applications, but it introduces a different behaviour and could break others.
Maybe adding a config option to queue_if_disconnected or something could be a solution?

@github-actions github-actions bot changed the title mqtt: Don't enqueue QoS>0 messages when publish in !MQTT_STATE_CONNEC… mqtt: Don't enqueue QoS>0 messages when publish in !MQTT_STATE_CONNEC… (IDFGH-4272) Nov 16, 2020
@AxelLin
Copy link
Contributor Author

AxelLin commented Nov 16, 2020

For QoS0, it simply returns -1 when in !MQTT_STATE_CONNECTED state.
I have no idea why it has different behavior for QoS>0 cases.
Why not return -1 so the behavior is consistent with QoS0?
And the request may be silently deleted due to reach OUTBOX_EXPIRED_TIMEOUT_MS if it takes too much time to reconnect.

Actually, I think this is a bug fix.
Consider about the mqtt broker shutdown or some netowrking issue casue connect broker failure for a period,
Allow enqueue QoS>1 request can make device run into OOM.
(And OOM usually won't make device panic or reboot, it just make device stop working)

BTW, I'm wondering why it could break some application.
I don't think people expect esp_mqtt_client_publish to work when it's not connected to broker.

@david-cermak
Copy link
Collaborator

Thanks for your further inputs. Indeed you're right, the change is helpful, make sense and could prevent the device getting into OOM. I might even agree that the publish API is inconsistent and not very much usable to keep publishing when disconnected just to queue messages into the outbox.

But this all is still besides the point that this PR is a breaking change and we cannot simply modify API behaviour like that. Moreover when we typically backport the submodule reference to all IDF release branches.

@AxelLin
Copy link
Contributor Author

AxelLin commented Nov 19, 2020

The reason I sent this fix is because I think current behavior is buggy.
If fix the behavior is not allow, I'll just close this pull request and checking the mqtt status in my application side.
Actually I belive most people use the mqtt this way, set a flag in MQTT_EVENT_CONNECTED/MQTT_EVENT_DISCONNECTED and do publish only when it is connected.

I don't like adding queue_if_disconnected configuration because most people won't really understand
why you need such configuration. In additonal, it does not address current issue at all.
I think it currently works just because of good luck because if reconnect takes longer time it will hit OOM.

BTW, this is probably off-topic, but actually the baviour was changed by
commit 6a0d1e7 "(support for qos1 and qos2 message retrasmission on reconnect").
In the initial version esp_mqtt_client_publish returns -1 for any QoS type.
see esp_mqtt_client_publish() in commit 083f878 "(Add support outbox, changed API").

@david-cermak
Copy link
Collaborator

I'm afraid we cannot accept this PR as is, unless a config option to enable/disable this change is added. Again I couldn't agree more with what you say:

Actually I belive most people use the mqtt this way...

most people won't really understand

The thing is that we cannot only think of most of the users, but all of them and maintain backward compatibility whenever possible. The config option might help and we can even turn it on on future releases.

BTW, this is probably off-topic, but actually the baviour was changed by ...

Not an off topic. Thanks for bringing this up! Yes, that probably wasn't the brightest decision, nor that was a breaking change at the time as it introduced queueing and resending for QoS>0, but this simply formed the API as is and as such needs to be maintained (at least for the stable IDF releases)

So please close this PR if you don't want to introduce additional configuration. Thank you for the contribution, anyway, we will have to address this issue in some way, plus maybe also add an event/notification on the deleted items from the outbox.

@AxelLin AxelLin closed this Nov 19, 2020
@AxelLin
Copy link
Contributor Author

AxelLin commented Nov 20, 2020

nor that was a breaking change at the time as it introduced queueing and resending for QoS>0, but this simply formed the API as is and as such needs to be maintained (at least for the stable IDF releases)

No, it's indeed a breaking change.
When it introduce queueing and resending for QoS>0, it didn't provide an config option to disable the new beahvior.
IMHO, even with an config option, the default should be "disable queueing and resending for QoS>0".

But since this change has been there for years, so the default will become "enable queueing and resending for QoS>0" if
you are going to add this config option.

espressif-bot pushed a commit to espressif/esp-idf that referenced this pull request Jan 15, 2021
* Queueing publish messages to outbox when the client is not connected (default=off -> messages are queued if disconnected)
* Use of incremental msg-id instead of random id (default=off -> msg-id uses platform_random())
* Posting a new event-id if a queued message gets deleted from the outbox (default=off -> events are not posted)

Detailed description of included `esp-mqtt` changes
(da850b0add1e71b3659bfac5d797cc834dc3e89b...9ea804e0ab5368d5ab53ae2301a5fec9d1f12f1a)
* mqtt: Remove unused mqtt_header_state_t
  - esp-mqtt commit: espressif/esp-mqtt@b7158a4
  - esp-mqtt MR: espressif/esp-mqtt!84
  - Merges espressif/esp-mqtt#180
* Cleanup public include dirs
  - esp-mqtt commit: espressif/esp-mqtt@f65d5d0
  - esp-mqtt MR: espressif/esp-mqtt!85
* Config: Add a new option to use incremental message id
  - esp-mqtt commit: espressif/esp-mqtt@8bb4a26
  - esp-mqtt MR: espressif/esp-mqtt!85
  - Closes espressif/esp-mqtt#176
* Publish: Add new API to enqueue qos>0 messages
  - esp-mqtt commit: espressif/esp-mqtt@dc7fd5c
  - esp-mqtt MR: espressif/esp-mqtt!85
  - Closes espressif/esp-mqtt#155
* Config: Add a new option to disable publishing when disconnected
  - esp-mqtt commit: espressif/esp-mqtt@f44dcb1
  - esp-mqtt MR: espressif/esp-mqtt!85
  - Related espressif/esp-mqtt#177
* Events: Add new event to report deleted messages from outbox
  - esp-mqtt commit: espressif/esp-mqtt@2e35d4d
  - esp-mqtt MR: espressif/esp-mqtt!85
* Publish: Allow for qos=0 messages to be stored using esp_mqtt_client_enqueue()
  - esp-mqtt commit: espressif/esp-mqtt@e2de0f3
  - esp-mqtt MR: espressif/esp-mqtt!85
@AxelLin AxelLin deleted the fix-publish-when-not-connected branch January 21, 2021 09:47
rich1111 pushed a commit to rich1111/esp-mqtt that referenced this pull request Mar 4, 2021
projectgus pushed a commit to espressif/esp-idf that referenced this pull request Jun 15, 2021
* Queueing publish messages to outbox when the client is not connected (default=off -> messages are queued if disconnected)
* Use of incremental msg-id instead of random id (default=off -> msg-id uses platform_random())
* Posting a new event-id if a queued message gets deleted from the outbox (default=off -> events are not posted)

Detailed description of included `esp-mqtt` changes
(da850b0add1e71b3659bfac5d797cc834dc3e89b...9ea804e0ab5368d5ab53ae2301a5fec9d1f12f1a)
* mqtt: Remove unused mqtt_header_state_t
  - esp-mqtt commit: espressif/esp-mqtt@b7158a4
  - esp-mqtt MR: espressif/esp-mqtt!84
  - Merges espressif/esp-mqtt#180
* Cleanup public include dirs
  - esp-mqtt commit: espressif/esp-mqtt@f65d5d0
  - esp-mqtt MR: espressif/esp-mqtt!85
* Config: Add a new option to use incremental message id
  - esp-mqtt commit: espressif/esp-mqtt@8bb4a26
  - esp-mqtt MR: espressif/esp-mqtt!85
  - Closes espressif/esp-mqtt#176
* Publish: Add new API to enqueue qos>0 messages
  - esp-mqtt commit: espressif/esp-mqtt@dc7fd5c
  - esp-mqtt MR: espressif/esp-mqtt!85
  - Closes espressif/esp-mqtt#155
* Config: Add a new option to disable publishing when disconnected
  - esp-mqtt commit: espressif/esp-mqtt@f44dcb1
  - esp-mqtt MR: espressif/esp-mqtt!85
  - Related espressif/esp-mqtt#177
* Events: Add new event to report deleted messages from outbox
  - esp-mqtt commit: espressif/esp-mqtt@2e35d4d
  - esp-mqtt MR: espressif/esp-mqtt!85
* Publish: Allow for qos=0 messages to be stored using esp_mqtt_client_enqueue()
  - esp-mqtt commit: espressif/esp-mqtt@e2de0f3
  - esp-mqtt MR: espressif/esp-mqtt!85
espressif-bot pushed a commit to espressif/esp-idf that referenced this pull request Jul 18, 2021
* Queueing publish messages to outbox when the client is not connected (default=off -> messages are queued if disconnected)
* Use of incremental msg-id instead of random id (default=off -> msg-id uses platform_random())
* Posting a new event-id if a queued message gets deleted from the outbox (default=off -> events are not posted)

Detailed description of included `esp-mqtt` changes
(da850b0add1e71b3659bfac5d797cc834dc3e89b...9ea804e0ab5368d5ab53ae2301a5fec9d1f12f1a)
* mqtt: Remove unused mqtt_header_state_t
  - esp-mqtt commit: espressif/esp-mqtt@b7158a4
  - esp-mqtt MR: espressif/esp-mqtt!84
  - Merges espressif/esp-mqtt#180
* Cleanup public include dirs
  - esp-mqtt commit: espressif/esp-mqtt@f65d5d0
  - esp-mqtt MR: espressif/esp-mqtt!85
* Config: Add a new option to use incremental message id
  - esp-mqtt commit: espressif/esp-mqtt@8bb4a26
  - esp-mqtt MR: espressif/esp-mqtt!85
  - Closes espressif/esp-mqtt#176
* Publish: Add new API to enqueue qos>0 messages
  - esp-mqtt commit: espressif/esp-mqtt@dc7fd5c
  - esp-mqtt MR: espressif/esp-mqtt!85
  - Closes espressif/esp-mqtt#155
* Config: Add a new option to disable publishing when disconnected
  - esp-mqtt commit: espressif/esp-mqtt@f44dcb1
  - esp-mqtt MR: espressif/esp-mqtt!85
  - Related espressif/esp-mqtt#177
* Events: Add new event to report deleted messages from outbox
  - esp-mqtt commit: espressif/esp-mqtt@2e35d4d
  - esp-mqtt MR: espressif/esp-mqtt!85
* Publish: Allow for qos=0 messages to be stored using esp_mqtt_client_enqueue()
  - esp-mqtt commit: espressif/esp-mqtt@e2de0f3
  - esp-mqtt MR: espressif/esp-mqtt!85
espressif-bot pushed a commit to espressif/esp-idf that referenced this pull request Jul 29, 2021
* Queueing publish messages to outbox when the client is not connected (default=off -> messages are queued if disconnected)
* Use of incremental msg-id instead of random id (default=off -> msg-id uses platform_random())
* Posting a new event-id if a queued message gets deleted from the outbox (default=off -> events are not posted)

Detailed description of included `esp-mqtt` changes
(da850b0add1e71b3659bfac5d797cc834dc3e89b...9ea804e0ab5368d5ab53ae2301a5fec9d1f12f1a)
* mqtt: Remove unused mqtt_header_state_t
  - esp-mqtt commit: espressif/esp-mqtt@b7158a4
  - esp-mqtt MR: espressif/esp-mqtt!84
  - Merges espressif/esp-mqtt#180
* Cleanup public include dirs
  - esp-mqtt commit: espressif/esp-mqtt@f65d5d0
  - esp-mqtt MR: espressif/esp-mqtt!85
* Config: Add a new option to use incremental message id
  - esp-mqtt commit: espressif/esp-mqtt@8bb4a26
  - esp-mqtt MR: espressif/esp-mqtt!85
  - Closes espressif/esp-mqtt#176
* Publish: Add new API to enqueue qos>0 messages
  - esp-mqtt commit: espressif/esp-mqtt@dc7fd5c
  - esp-mqtt MR: espressif/esp-mqtt!85
  - Closes espressif/esp-mqtt#155
* Config: Add a new option to disable publishing when disconnected
  - esp-mqtt commit: espressif/esp-mqtt@f44dcb1
  - esp-mqtt MR: espressif/esp-mqtt!85
  - Related espressif/esp-mqtt#177
* Events: Add new event to report deleted messages from outbox
  - esp-mqtt commit: espressif/esp-mqtt@2e35d4d
  - esp-mqtt MR: espressif/esp-mqtt!85
* Publish: Allow for qos=0 messages to be stored using esp_mqtt_client_enqueue()
  - esp-mqtt commit: espressif/esp-mqtt@e2de0f3
  - esp-mqtt MR: espressif/esp-mqtt!85
espressif-bot pushed a commit to espressif/esp-idf that referenced this pull request Jul 30, 2021
* Queueing publish messages to outbox when the client is not connected (default=off -> messages are queued if disconnected)
* Use of incremental msg-id instead of random id (default=off -> msg-id uses platform_random())
* Posting a new event-id if a queued message gets deleted from the outbox (default=off -> events are not posted)

Detailed description of included `esp-mqtt` changes
(da850b0add1e71b3659bfac5d797cc834dc3e89b...9ea804e0ab5368d5ab53ae2301a5fec9d1f12f1a)
* mqtt: Remove unused mqtt_header_state_t
  - esp-mqtt commit: espressif/esp-mqtt@b7158a4
  - esp-mqtt MR: espressif/esp-mqtt!84
  - Merges espressif/esp-mqtt#180
* Cleanup public include dirs
  - esp-mqtt commit: espressif/esp-mqtt@f65d5d0
  - esp-mqtt MR: espressif/esp-mqtt!85
* Config: Add a new option to use incremental message id
  - esp-mqtt commit: espressif/esp-mqtt@8bb4a26
  - esp-mqtt MR: espressif/esp-mqtt!85
  - Closes espressif/esp-mqtt#176
* Publish: Add new API to enqueue qos>0 messages
  - esp-mqtt commit: espressif/esp-mqtt@dc7fd5c
  - esp-mqtt MR: espressif/esp-mqtt!85
  - Closes espressif/esp-mqtt#155
* Config: Add a new option to disable publishing when disconnected
  - esp-mqtt commit: espressif/esp-mqtt@f44dcb1
  - esp-mqtt MR: espressif/esp-mqtt!85
  - Related espressif/esp-mqtt#177
* Events: Add new event to report deleted messages from outbox
  - esp-mqtt commit: espressif/esp-mqtt@2e35d4d
  - esp-mqtt MR: espressif/esp-mqtt!85
* Publish: Allow for qos=0 messages to be stored using esp_mqtt_client_enqueue()
  - esp-mqtt commit: espressif/esp-mqtt@e2de0f3
  - esp-mqtt MR: espressif/esp-mqtt!85
david-cermak added a commit that referenced this pull request Dec 16, 2022
* Queueing publish messages to outbox when the client is not connected (default=off -> messages are queued if disconnected)
* Use of incremental msg-id instead of random id (default=off -> msg-id uses platform_random())
* Posting a new event-id if a queued message gets deleted from the outbox (default=off -> events are not posted)

Detailed description of included `esp-mqtt` changes
(da850b0...9ea804e)
* mqtt: Remove unused mqtt_header_state_t
  - esp-mqtt commit: b7158a4
  - esp-mqtt MR: espressif/esp-mqtt!84
  - Merges #180
* Cleanup public include dirs
  - esp-mqtt commit: f65d5d0
  - esp-mqtt MR: espressif/esp-mqtt!85
* Config: Add a new option to use incremental message id
  - esp-mqtt commit: 8bb4a26
  - esp-mqtt MR: espressif/esp-mqtt!85
  - Closes #176
* Publish: Add new API to enqueue qos>0 messages
  - esp-mqtt commit: dc7fd5c
  - esp-mqtt MR: espressif/esp-mqtt!85
  - Closes #155
* Config: Add a new option to disable publishing when disconnected
  - esp-mqtt commit: f44dcb1
  - esp-mqtt MR: espressif/esp-mqtt!85
  - Related #177
* Events: Add new event to report deleted messages from outbox
  - esp-mqtt commit: 2e35d4d
  - esp-mqtt MR: espressif/esp-mqtt!85
* Publish: Allow for qos=0 messages to be stored using esp_mqtt_client_enqueue()
  - esp-mqtt commit: e2de0f3
  - esp-mqtt MR: espressif/esp-mqtt!85
egnor pushed a commit to egnor/esp-mqtt that referenced this pull request Dec 23, 2022
* Queueing publish messages to outbox when the client is not connected (default=off -> messages are queued if disconnected)
* Use of incremental msg-id instead of random id (default=off -> msg-id uses platform_random())
* Posting a new event-id if a queued message gets deleted from the outbox (default=off -> events are not posted)

Detailed description of included `esp-mqtt` changes
(da850b0...9ea804e)
* mqtt: Remove unused mqtt_header_state_t
  - esp-mqtt commit: espressif@b7158a4
  - esp-mqtt MR: espressif/esp-mqtt!84
  - Merges espressif#180
* Cleanup public include dirs
  - esp-mqtt commit: espressif@f65d5d0
  - esp-mqtt MR: espressif/esp-mqtt!85
* Config: Add a new option to use incremental message id
  - esp-mqtt commit: espressif@8bb4a26
  - esp-mqtt MR: espressif/esp-mqtt!85
  - Closes espressif#176
* Publish: Add new API to enqueue qos>0 messages
  - esp-mqtt commit: espressif@dc7fd5c
  - esp-mqtt MR: espressif/esp-mqtt!85
  - Closes espressif#155
* Config: Add a new option to disable publishing when disconnected
  - esp-mqtt commit: espressif@f44dcb1
  - esp-mqtt MR: espressif/esp-mqtt!85
  - Related espressif#177
* Events: Add new event to report deleted messages from outbox
  - esp-mqtt commit: espressif@2e35d4d
  - esp-mqtt MR: espressif/esp-mqtt!85
* Publish: Allow for qos=0 messages to be stored using esp_mqtt_client_enqueue()
  - esp-mqtt commit: espressif@e2de0f3
  - esp-mqtt MR: espressif/esp-mqtt!85
egnor pushed a commit to egnor/esp-mqtt that referenced this pull request Dec 23, 2022
* Queueing publish messages to outbox when the client is not connected (default=off -> messages are queued if disconnected)
* Use of incremental msg-id instead of random id (default=off -> msg-id uses platform_random())
* Posting a new event-id if a queued message gets deleted from the outbox (default=off -> events are not posted)

Detailed description of included `esp-mqtt` changes
(da850b0...9ea804e)
* mqtt: Remove unused mqtt_header_state_t
  - esp-mqtt commit: espressif@b7158a4
  - esp-mqtt MR: espressif/esp-mqtt!84
  - Merges espressif#180
* Cleanup public include dirs
  - esp-mqtt commit: espressif@f65d5d0
  - esp-mqtt MR: espressif/esp-mqtt!85
* Config: Add a new option to use incremental message id
  - esp-mqtt commit: espressif@8bb4a26
  - esp-mqtt MR: espressif/esp-mqtt!85
  - Closes espressif#176
* Publish: Add new API to enqueue qos>0 messages
  - esp-mqtt commit: espressif@dc7fd5c
  - esp-mqtt MR: espressif/esp-mqtt!85
  - Closes espressif#155
* Config: Add a new option to disable publishing when disconnected
  - esp-mqtt commit: espressif@f44dcb1
  - esp-mqtt MR: espressif/esp-mqtt!85
  - Related espressif#177
* Events: Add new event to report deleted messages from outbox
  - esp-mqtt commit: espressif@2e35d4d
  - esp-mqtt MR: espressif/esp-mqtt!85
* Publish: Allow for qos=0 messages to be stored using esp_mqtt_client_enqueue()
  - esp-mqtt commit: espressif@e2de0f3
  - esp-mqtt MR: espressif/esp-mqtt!85
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants