From fda26f20f4c701a36553792f4fcbb176a222e5fc Mon Sep 17 00:00:00 2001 From: Emiel Bruijntjes Date: Fri, 16 Jun 2017 11:17:13 +0100 Subject: [PATCH] update the readme, heartbeats are now disabled by default, only the libev implementation has enabled them, resolves #137 --- README.md | 60 +++++++++++++++++++++++++++++++++++++ include/connectionhandler.h | 4 +-- include/libev.h | 7 ++--- 3 files changed, 64 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index b324354..28b1564 100644 --- a/README.md +++ b/README.md @@ -434,6 +434,66 @@ libevent. For other event loops (like libuv and boost asio) we do not yet have such examples. +HEARTBEATS +========== + +The AMQP protocol supports *heartbeats*. If this heartbeat feature is enabled, the +client and the server negotiate a heartbeat interval during connection setup, and +they agree to send at least *some kind of data* over the connection during every +iteration of that interval. The normal data that is sent over the connection (like +publishing or consuming messages) is normally sufficient to keep the connection alive, +but if the client or server was idle during the negotiated interval time, a dummy +heartbeat message must be sent instead. + +The default behavior of the AMQP-CPP library is to disable heartbeats. The +proposed heartbeat interval of the server during connection setup (the server +normally suggests an interval of 60 seconds) is vetoed by the AMQP-CPP library so +no heartbeats are ever needed to be sent over the connection. This means that you +can safely keep your AMQP connection idle for as long as you like, and/or run long +lasting algorithms after you've consumed a message from RabbitMQ, without having +to worry about the connection being idle for too long. + +You can however choose to enable these heartbeats. If you want to enable heartbeats, +simple implement the onNegotiate() method inside your ConnectionHandler or +TcpHandler class and have it return the interval that you find appropriate. + +````c++ +#include + +class MyTcpHandler : public AMQP::TcpHandler +{ + /** + * Method that is called when the server tries to negotiate a heartbeat + * interval, and that is overridden to get rid of the default implementation + * (which vetoes the suggested heartbeat interval), and accept the interval + * instead. + * @param connection The connection on which the error occured + * @param interval The suggested interval in seconds + */ + virtual void onNegotiate(AMQP::TcpConnection *connection, uint16_t interval) + { + // we accept the suggestion from the server, but if the interval is smaller + // that one minute, we will use a one minute interval instead + if (interval < 60) interval = 60; + + // @todo + // set a timer in your event loop, and make sure that you call + // connection->heartbeat() every _interval_ seconds. + + // return the interval that we want to use + return interval; + } +}; +```` + +If you have enabled heartbeats, it is your own responsibility to ensure that the +```connection->heartbeat()``` method is called at least once during this period, +or that you call one of the other channel or connection methods to send data +over the connection. + +In the libev event loop implementation the heartbeats are enabled by default. + + CHANNELS ======== diff --git a/include/connectionhandler.h b/include/connectionhandler.h index d2c4786..c68af2a 100644 --- a/include/connectionhandler.h +++ b/include/connectionhandler.h @@ -62,8 +62,8 @@ public: */ virtual uint16_t onNegotiate(Connection *connection, uint16_t interval) { - // default implementation, suggested heartbeat is ok - return interval; + // default implementation, disable heartbeats + return 0; } /** diff --git a/include/libev.h b/include/libev.h index 21577a4..886f41d 100644 --- a/include/libev.h +++ b/include/libev.h @@ -258,16 +258,13 @@ protected: */ virtual uint16_t onNegotiate(TcpConnection *connection, uint16_t interval) override { - // call base to find out the timeout that the client wants - interval = TcpHandler::onNegotiate(connection, interval); - - // skip if base does not want a timeout + // skip if no heartbeats are needed if (interval == 0) return 0; // set the timer _timer.set(connection, interval); - // done + // we agree with the interval return interval; }