ClickHouse/src/Storages/RabbitMQ/RabbitMQConnection.cpp
2021-09-11 20:40:18 +03:00

125 lines
3.0 KiB
C++

#include "RabbitMQConnection.h"
#include <common/logger_useful.h>
#include <IO/WriteHelpers.h>
namespace DB
{
static const auto CONNECT_SLEEP = 200;
static const auto RETRIES_MAX = 20;
RabbitMQConnection::RabbitMQConnection(const RabbitMQConfiguration & configuration_, Poco::Logger * log_)
: configuration(configuration_)
, log(log_)
, event_handler(loop.getLoop(), log)
{
}
String RabbitMQConnection::connectionInfoForLog() const
{
return configuration.host + ':' + toString(configuration.port);
}
bool RabbitMQConnection::isConnected()
{
std::lock_guard lock(mutex);
return isConnectedImpl();
}
bool RabbitMQConnection::connect()
{
std::lock_guard lock(mutex);
connectImpl();
return event_handler.connectionRunning();
}
bool RabbitMQConnection::reconnect()
{
std::lock_guard lock(mutex);
if (isConnectedImpl())
return true;
disconnectImpl();
/// This will force immediate closure if not yet closed
if (!connection->closed())
connection->close(true);
LOG_TRACE(log, "Trying to restore connection to {}", connectionInfoForLog());
connectImpl();
return event_handler.connectionRunning();
}
ChannelPtr RabbitMQConnection::createChannel()
{
std::lock_guard lock(mutex);
if (!isConnectedImpl())
return nullptr;
return std::make_unique<AMQP::TcpChannel>(connection.get());
}
void RabbitMQConnection::disconnect(bool immediately)
{
std::lock_guard lock(mutex);
disconnectImpl(immediately);
}
void RabbitMQConnection::heartbeat()
{
std::lock_guard lock(mutex);
connection->heartbeat();
}
bool RabbitMQConnection::closed()
{
std::lock_guard lock(mutex);
return connection->closed();
}
bool RabbitMQConnection::isConnectedImpl() const
{
return event_handler.connectionRunning() && connection->usable();
}
void RabbitMQConnection::connectImpl()
{
if (configuration.connection_string.empty())
{
AMQP::Login login(configuration.username, configuration.password);
AMQP::Address address(configuration.host, configuration.port, login, configuration.vhost, configuration.secure);
connection = std::make_unique<AMQP::TcpConnection>(&event_handler, address);
}
else
{
AMQP::Address address(configuration.connection_string);
connection = std::make_unique<AMQP::TcpConnection>(&event_handler, address);
}
auto cnt_retries = 0;
while (!connection->ready() && cnt_retries++ != RETRIES_MAX)
{
event_handler.iterateLoop();
std::this_thread::sleep_for(std::chrono::milliseconds(CONNECT_SLEEP));
}
}
void RabbitMQConnection::disconnectImpl(bool immediately)
{
connection->close(immediately);
/** Connection is not closed immediately (firstly, all pending operations are completed, and then
* an AMQP closing-handshake is performed). But cannot open a new connection until previous one is properly closed
*/
size_t cnt_retries = 0;
while (!connection->closed() && cnt_retries++ != RETRIES_MAX)
event_handler.iterateLoop();
}
}