Skip to content

Add support for outgoing heartbeats - #72

Merged
jmglsn merged 5 commits into
masterfrom
feature/heartbeats
Jun 11, 2017
Merged

Add support for outgoing heartbeats#72
jmglsn merged 5 commits into
masterfrom
feature/heartbeats

Conversation

@jmglsn

@jmglsn jmglsn commented May 29, 2017

Copy link
Copy Markdown
Member

In #60 we see that heartbeats support might help to avoid broken connections or at least they can reduce the lack from error to notification.

This only includes support for outgoing beats, incoming beats are not yet included. I could imagine to use the same observer infrastructure to offer support for incoming beat detection.

andrewbelcher and others added 2 commits May 25, 2017 22:03
- add observer based heartbeat emitter, which must be added to the connection if outgoing heartbeats are wanted
- allow to use heartbeats when connection is reopened by server
- fix older test cases to be more precise and fix preconditions
Comment thread src/Stomp/Client.php
}

/**
* Set the desired heartbeat for the connection.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

we should spent a small sentence why one would want to use a heartbeat (which problem it solves conceptionally)

public function receivedFrame(Frame $frame);

/**
* Indicates that a frame has been transmitted.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

the word transmit does not imply a direction, does it?

received fits as it describes a incoming frame, but transmitted isnt a good fit IMO.

maybe sentFrame or somthing?

* Adds new observers to the collection.
*
* @param ConnectionObserver $observer
* @return ConnectionObserverCollection

@staabm staabm May 30, 2017

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

$this (same in other spots of this class)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I used to replace $this with the actual return type since some time now. I also see that at symfony code - I would just like to change it to something like @return ConnectionObserverCollection this collection - what do you think about that?

*
* @return ConnectionObserver[]
*/
public function getObserver()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

plural Observers

*/
public function receivedFrame(Frame $frame)
{
if ($frame->getCommand() === 'CONNECTED') {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

should we have constants for this magic strings?

*/
private function getHeartbeats(Frame $frame)
{
$beats = $frame['heart-beat'];

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

do we need an isset ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The ArrayAccess implementation of Frame will return null if the header is not available. That simplified some work with the headers.

Comment thread src/Stomp/Network/Connection.php Outdated
if (!@fwrite($this->connection, $data, strlen($data))) {
throw new ConnectionException('Was not possible to write frame!', $this->activeHost);
}
$this->getObserver()->transmittedFrame($stompFrame);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

we shouldnt use the getter inside off this class... this is a very hot path of our lib .. just use $this->observer instead.

I have the same feeling for isConnected(), hasDataToRead() etc. within this class, but this shouldn't be changed with this PR. I guess we can speedup the client a lot when we prevent this calls and just inline the code (the methods should still be preserved for public consumption and BC)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

That's right we should check that in our next release.

@staabm

staabm commented May 30, 2017

Copy link
Copy Markdown
Member

Great Job, just a few minor nits/questions!

@jmglsn

jmglsn commented May 31, 2017

Copy link
Copy Markdown
Member Author

@staabm - Thank you for the review 👍 I'll apply the notes within a few days.

@jmglsn

jmglsn commented May 31, 2017

Copy link
Copy Markdown
Member Author

Also updated the examples stomp-php/stomp-php-examples@fb02c79.

If everything is fine we can squeeze and merge this.

* file that was distributed with this source code.
*/

namespace Stomp\Network\Observer\Heartbeat;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is a single class Namspace.. should we instead strip heartbeat from the NS and name the class HeartbeatEmitter ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes, when I added it I thought about the Monitor but there will be never more than two, so it's fine to Prefix them.

Comment thread src/Stomp/Client.php
* within an interval - to indicate that the connection is still stable. If client and server agree on a beat and
* the interval passes without any data activity / beats the connection will be considered as broken and closed.
*
* If you define a heartbeat, you must assure that your application will send data within the interval.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

hmm isn't it exactly the opposite? in case you use heartbeats you dont need to send data in certain intervalls as the client will automatically sent a hearbeat to keep the connection alive..?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

jein - without a heartbeat declaration you can send data whenever you want, you could even add some minutes of sleep between the communication.
With heartbeats enabled you must do something within the interval.
The emitter is not automatically attached to the connection. Maybe this description is not yet good enough yet. But it's not that easy, hm...

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

hm does it make sense to enable hearbeats but dont add the emitter?

@jmglsn jmglsn Jun 1, 2017

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I think so, for those who don't like to add the overhead and expect to send data within the interval.

*
* @return void
*/
private function notifyBeat()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

rememberBeat?

}

/**
* Returns the heart beat header.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

hearbeat single word?

if ($frame->getCommand() === Emitter::FRAME_CLIENT_CONNECT) {
$beats = $this->getHeartbeats($frame);
$this->intervalClient = $beats[0];
$this->notifyBeat();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

do we need enabled=true in this IF?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

No, it should be possible to support the RabbitMQ "Implicit Connect" (https://www.rabbitmq.com/stomp.html) this works without a CONNECT frame - so the enabled flag is here to query the state, but not to control it. (see testEmitterActivatedIfServerRequestsBeatsAndNoConnectFrameWasSend)

*
* @param float $intervalUsage
*/
public function setIntervalUsage($intervalUsage)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

as this value should be set before the emitter gets active, should it be a constructor arg instead?

{
if ($this->isConnected()) {
return (!@fwrite($this->connection, "\n", 1) == true);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Intentionally not a strict comparison?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It's easy to see that this might return nothing good...
Good reason to wait until Tuesday before opening a PR the next time ;)

@jmglsn
jmglsn merged commit c1118c1 into master Jun 11, 2017
@jmglsn
jmglsn deleted the feature/heartbeats branch June 11, 2017 09:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants