Hello RabbitMQ-C Community,
We're using rabbitmq-c (v0.15.0) in a long-running Unreal Engine client and are running into a stability issue related to message acknowledgment.
The Problem: Our client successfully consumes a message, processes it, and then calls amqp_basic_ack. Very shortly after, the connection fails with AMQP_STATUS_UNEXPECTED_STATE (0xfffffff0). This causes a disconnect, and the broker (correctly) redelivers the message, creating a processing loop.
Our Investigation: In our original code, after calling amqp_basic_ack, we were calling amqp_simple_wait_frame_noblock in an attempt to "flush" the ACK and confirm it was sent.
We now believe this was the cause of the error. Our understanding is that basic.ack is a one-way signal, and the broker does not send a reply. By calling amqp_simple_wait_frame_noblock, we were accidentally reading the next available frame (like a heartbeat or another message), which desynchronized the library's state and caused the UNEXPECTED_STATE error.
Our Proposed Fix: We have changed our FlushDeliveryFrame function to remove any socket-reading calls like amqp_simple_wait_frame_noblock or amqp_get_rpc_reply after an ACK/NACK. The function now only calls amqp_maybe_release_buffers(ConnectionState) to flush the outbound write buffer.
Our Questions:
Is this new approach (calling amqp_basic_ack followed only by amqp_maybe_release_buffers) the correct, reliable way to acknowledge a message?
Our primary goal is "at-least-once" delivery, so we are concerned about reliability. If our client processes a message and then crashes just after the amqp_basic_ack call, how can we be as certain as possible that the ACK frame was handed off to the OS/network stack? Is there a recommended "blocking write-flush" pattern that doesn't involve reading from the socket?
Any advice on the best practice for ensuring ACK durability from the client side would be extremely helpful.
Thank you!