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

Connection heartbeat arg description doesn't match implementation #91

Open
vitaly-krugl opened this issue Feb 16, 2016 · 13 comments
Open

Comments

@vitaly-krugl
Copy link

The heartbeat arg description 73cd9b1#diff-a440ae8b97ad1a5653b91743003e498aR334 is

heartbeat Default None (disabled). If 0, broker assigned. If >0, negotiated with broker.

The implementation appears to be that if user passed heartbeat=None, then the heartbeat value is broker-assigned; if user passed heartbeat=0, then heartbeats would be disabled. The quoted description is the reverse of what actually happens in the code.

        if self.connection._heartbeat is None:
            self.connection._heartbeat = method_frame.args.read_short()
@vitaly-krugl vitaly-krugl mentioned this issue Feb 16, 2016
@vitaly-krugl
Copy link
Author

CC @josegonzalez

@josegonzalez
Copy link
Contributor

I don't know. It seems like the documentation is right, but its hard to figure it out based on the naming of the heartbeat variable across the codebase.

@vitaly-krugl
Copy link
Author

The negotiation logic is:

        if self.connection._heartbeat is None:
            self.connection._heartbeat = method_frame.args.read_short()

which accepts broker's value if user's value is None. However, the description says "Default None (disabled). If 0, broker assigned.", which is absolutely not the same thing.

@josegonzalez
Copy link
Contributor

The logic here actually doesn't send the heartbeat either way though?

        if self.connection._heartbeat:
            if time.time() >= (self._last_heartbeat_send + 0.9 *
                               self.connection._heartbeat):
                self.send_frame(HeartbeatFrame(self.channel_id))
                self._last_heartbeat_send = time.time()

@vitaly-krugl
Copy link
Author

Correct, but the broker cannot pass the value None in Connection.Tune; the value None could only have come from the user, and after negotiation self.connection._heartbeat will not be None. If the user passes None, the only way that self.connection._heartbeat could end up as 0 after negotiation is if the broker passed 0 in Connection.Tune

@josegonzalez
Copy link
Contributor

True, but isn't _heartbeat set by the consumer?

@vitaly-krugl
Copy link
Author

It's set from user's arg here:

self._heartbeat = kwargs.get('heartbeat')
and then overridden here
self.connection._heartbeat = method_frame.args.read_short()

@josegonzalez
Copy link
Contributor

@vitaly-krugl note: since we deployed this change in production, we no longer get heartbeat timeouts in related services. This definitely merits further research though.

@vitaly-krugl
Copy link
Author

@josegonzalez, this makes sense, because your change heartbeat=0 disables heartbeats on both client and broker sides of the connection.

@josegonzalez
Copy link
Contributor

So are the docs wrong?

@vitaly-krugl
Copy link
Author

@josegonzalez, yes the docs are wrong, and that's the gist of this issue.

@josegonzalez
Copy link
Contributor

@vitaly-krugl so one reason we made this change was an upgrade to RabbitMQ moved the timeout from 5 minutes to 1 minute, impacting some of our longer running jobs (map and ticket processing). What you're saying makes it sound like there is an issue in our networking in regards to sending the heartbeats maybe, especially if the default of None should make it respect server heartbeats...

@josegonzalez
Copy link
Contributor

Hmmm, seems like us not sending heartbeats was unrelated. So then yes, the docs here are almost certainly wrong, heh.

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

No branches or pull requests

2 participants