-
Notifications
You must be signed in to change notification settings - Fork 273
Description
As discussed in #230, there are a variety of situations where having separate locks for outbox operations would be desirable.
-
In the case of
esp_mqtt_client_enqueue, if the client is locked for extended periods of time due to waiting onesp_transport_write/ network timeout, new messages cannot be enqueued quickly from an external task when locks are enabled. A suitable workaround was discussed, but is a bit ugly from a user implementation perspective (e.g. having to define a message container type, alloc, dealloc, implement user events). Having a separate lock that for outbox for msg enqueue/dequeue would result in something that is much closer to a non-blocking API. -
As discussed in this comment, having a separate outbox lock would allow for the user to implement additional outbox logic such as limiting the number of in-flight messages, checking if a certain
msg_idwas delivered yet, etc.
On first glance it seems this might be tricky to implement, since outbox_enqueue, outbox_set_pending, etc are often referencing pending_msg_id.
But thinking about it more, all of the outbox APIs are already pretty self-contained, and enqueueing new messages would really only need to know about connection->last_message_id which could be moved to the outbox handle. Then perhaps if the outbox was also used for qos0 messages, it would be possible to call mqtt_client_enqueue_priv without necessarily needing to lock the client, since it appears the values are just assigned to client->mqtt_state, and then copied back over in mqtt_enqueue.
The caveats I see are mqtt_resend_queued uses a dequeued outbox item, which might cause issues. And also not sure how about logic around fragmented messages. It might be easier to make it so that esp_mqtt_client_enqueue does not use mqtt_client_enqueue_priv and instead just creates a outbox_message_t and calls outbox_enqueue.