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

Implement heartbeat functionality #224

Merged
merged 1 commit into from
Aug 12, 2019
Merged

Conversation

futile
Copy link
Contributor

@futile futile commented Aug 4, 2019

Make sure that connections don't time out if we don't want them to, by
regularly sending special, empty "heartbeat" packets on connections that we
have not sent on for some time.

These heartbeats have the new packet type PacketType::Heartbeat, which makes it possible to differentiate them from empty packets sent by a user.

The heartbeat interval can be configured and disabled/enabled via Config::heartbeat_interval.

Note: Currently these heartbeats can not be explicity disabled (but you can set a very long heartbeat interval), but that should not be hard to add, if desired. Edit: Heartbeats can now be disabled.

@codecov
Copy link

codecov bot commented Aug 4, 2019

Codecov Report

Merging #224 into master will decrease coverage by 0.03%.
The diff coverage is 96.96%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #224      +/-   ##
==========================================
- Coverage   97.49%   97.45%   -0.04%     
==========================================
  Files          25       25              
  Lines        2357     2439      +82     
==========================================
+ Hits         2298     2377      +79     
- Misses         59       62       +3
Impacted Files Coverage Δ
src/packet/enums.rs 97.1% <100%> (+0.17%) ⬆️
src/packet/header/standard_header.rs 98.64% <100%> (+0.05%) ⬆️
src/net/virtual_connection.rs 96.91% <100%> (+0.1%) ⬆️
src/net/connection.rs 100% <100%> (ø) ⬆️
src/config.rs 100% <100%> (ø) ⬆️
src/net/socket.rs 96.05% <95.58%> (-0.18%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 3d8c65f...74dd68f. Read the comment docs.

@futile
Copy link
Contributor Author

futile commented Aug 4, 2019

If I understand the codecov report correctly, everything except for errors that can be returned from Socket::send_to is covered. Any ideas on how to test these remaining cases? The same kind of error is also returned by Socket::handle_idle_clients, but it's also not tested there, so I can't test it the same way.

src/config.rs Outdated
@@ -52,6 +54,7 @@ impl Default for Config {
Self {
blocking_mode: false,
idle_connection_timeout: Duration::from_secs(5),
heartbeat_interval: Duration::from_secs(2),
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should probably, in the future, have this calculated based on the current network circumstances. With two seconds this is safe, we might as well move it up to 3, because the idling time is 5 seconds, then the heartbeat has a total time of 2 seconds to arrive at the client.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I thought about that as well, but didn't want to add RTT calculations into it (for now). Although I agree that that is probably a good idea here.

I chose 2 seconds because then if one heartbeat packet is lost, we have enough time (probably) to send another one before the connection times out. Then again, this really depends on the idle_connection_timeout value of the receiver, so the user currently has to adjust this value to their wishes anyway.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I can understand that I am not too certain about our RTT calculations as well, so I am fine with having this statically typed now. And figure out a way to do it based on the current internet speed in the future.

if let Err(e) = self.handle_idle_clients(time) {
error!("Encountered an error when sending TimeoutEvent: {:?}", e);
}

// Finally send heartbeat packets to connections that require them
if let Err(e) = self.send_heartbeat_packets(time) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed, I prefer to have this optional.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, should it be enabled or disabled by default?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made heartbeats disabled by default, and the config value is now an Option<Duration>, where None disables and Some(Duration) enables heartbeats.

@TimonPost
Copy link
Owner

Thanks for the PR, I do have one question are the acknowledgments also sent when the user only sents unreliable packets, because I don't see much-added value to have a heartbeat for those guarantees.

@futile
Copy link
Contributor Author

futile commented Aug 4, 2019

I think the CI failure is spurious. I'm also working from windows and also saw it once (for no reason). Also I think something similar happened during my previous documentation-PR?

@futile
Copy link
Contributor Author

futile commented Aug 4, 2019

Thanks for the PR, I do have one question are the acknowledgments also sent when the user only sents unreliable packets, because I don't see much-added value to have a heartbeat for those guarantees.

I'm not quite sure what you mean, but heartbeats are currently send as unreliable and unordered, so there are no acknowledgments sent out for heartbeats atm. Did I understand your question correctly?

Make sure that connections don't time out if we don't want them to, by
regularly sending special, empty "heartbeat" packets on connections that we
have not sent on for some time.

The heartbeat interval can be configured and enabled/disabled via
`Config::heartbeat_interval'.
@TimonPost
Copy link
Owner

I meant more in the way of, when sending packets, we can do use unreliably unordered to so for example. For unreliable packets, we do not have any internal state as we have for reliable ordered. So we might not care about the client to disconnect, on the other hand, I do think now, that you might also want to keep track of connected clients when only sending unreliable packets. So is not a direct problem, as long the heartbeat is optional im OK with it

Copy link
Contributor

@jstnlef jstnlef left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me 👍.

@jstnlef
Copy link
Contributor

jstnlef commented Aug 12, 2019

@TimonPost I believe that maintaining connection is an orthogonal concern to whether or not reliable packets are sent and having the option to ensure heartbeats are sent when a client is idling seems reasonable to me.

@futile
Copy link
Contributor Author

futile commented Aug 12, 2019

Thanks for the review! :)

@TimonPost
Copy link
Owner

Agreed, let's merge this!

@TimonPost
Copy link
Owner

bors r=TimonPost, jstnlef

bors bot added a commit that referenced this pull request Aug 12, 2019
224: Implement heartbeat functionality r=TimonPost,jstnlef a=futile

Make sure that connections don't time out if we don't want them to, by
regularly sending special, empty "heartbeat" packets on connections that we
have not sent on for some time.

These heartbeats have the new packet type `PacketType::Heartbeat`, which makes it possible to differentiate them from empty packets sent by a user.

The heartbeat interval can be configured and disabled/enabled via `Config::heartbeat_interval`.

~~Note: Currently these heartbeats can not be explicity disabled (but you can set a very long heartbeat interval), but that should not be hard to add, if desired.~~ Edit: Heartbeats can now be disabled.

Co-authored-by: Felix Rath <felix.rath@rwth-aachen.de>
@bors
Copy link
Contributor

bors bot commented Aug 12, 2019

Timed out

@TimonPost TimonPost merged commit 58630ed into TimonPost:master Aug 12, 2019
jstnlef pushed a commit to jstnlef/laminar that referenced this pull request Oct 12, 2019
jstnlef pushed a commit that referenced this pull request Oct 12, 2019
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.

3 participants