Skip to content

Honour max_packets in Client.loop_read - #963

Closed
Eryx-Z wants to merge 1 commit into
eclipse-paho:masterfrom
Eryx-Z:fix/loop-read-max-packets
Closed

Eryx-Z wants to merge 1 commit into
eclipse-paho:masterfrom
Eryx-Z:fix/loop-read-max-packets

Conversation

@Eryx-Z

@Eryx-Z Eryx-Z commented Oct 16, 2026

Copy link
Copy Markdown

Description

Client.loop_read(max_packets=...) previously overwrote the caller-supplied bound with len(_out_messages) + len(_in_messages). For QoS 0 traffic that sum is usually 0, so every call handled exactly one packet regardless of the argument.

Home Assistant and similar asyncio integrations call loop_read(500) expecting to batch available packets. This change uses max(max_packets, pending, 1) so:

  • the default of 1 keeps historical QoS 0 behaviour
  • pending QoS > 0 messages are still fully drained when that count exceeds the caller bound
  • callers can raise the upper bound for QoS 0 batching

Testing

Added test_loop_read_honours_max_packets (fake broker, five QoS 0 PUBLISH packets, loop_read(10) receives all five).

Closes #962

loop_read previously overwrote the caller-supplied max_packets with
the count of in-flight QoS > 0 messages, so QoS 0 traffic always
processed one packet per call. Use max(caller value, pending, 1)
instead so the default of 1 keeps historical behaviour while
callers such as Home Assistant can batch reads.

Closes eclipse-paho#962

Signed-off-by: Eryx-Z <Eryx-Z@users.noreply.github.com>
@Eryx-Z

Eryx-Z commented Oct 17, 2026

Copy link
Copy Markdown
Author

Closing for now; may revisit later.

@Eryx-Z Eryx-Z closed this Oct 17, 2026
@JamesParrott

JamesParrott commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

@Eryx-Z It's your decision, but LGTM. At first glance, your fix looks like exactly the correct one (in my opinion):

Replace:

        max_packets = len(self._out_messages) + len(self._in_messages)
        if max_packets < 1:
            max_packets = 1

with:

        pending = len(self._out_messages) + len(self._in_messages)
        max_packets = max(max_packets, pending, 1)

Why is anything more than that required? Is something else using max_packets too, or were there other unforseen consequences, or something to resolve in the tests?

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.

loop_read() ignores its max_packets argument

2 participants