Async ACK handling can block indefinitely
See original GitHub issueAs a gate in the publish function, the publish routine will put a None marker on the blocking queue, which will block as designed if the queue is full:
await self._pending_pub_acks_queue.put(None)
However, the marker is only remove from the queue if the item is ACK’d. If the ACK never arrives, either in the synchronous or asynchronous case, the marker is not removed from the queue. Over time, if there are enough dropped ACK’s the _pending_pub_acks_queue will fill, blocking publishing indefinitely.
In addition, for the async case, there’s no way for the caller to remove the outstanding ACK element in ‘self._pub_ack_map’ directly if the ACK never arrives. It would either have to hack it or fake the callback. Also,
cb = self._pub_ack_map[pub_ack.guid]
await cb(pub_ack)
del self._pub_ack_map[pub_ack.guid]
Should be written as:
cb = self._pub_ack_map[pub_ack.guid]
del self._pub_ack_map[pub_ack.guid]
await cb(pub_ack)
To defend leak on exception in the callback.
To remedy, either the library should manage timeouts much like the golang equivalent, or an api should be provided for the user to cancel an outstanding asynchronous publish.
Issue Analytics
- State:
- Created 5 years ago
- Reactions:1
- Comments:5
Top GitHub Comments
+1
Looks like it will block if you get enough ACK drops in the synchronous case as well.