RpcManager: Try to reconnect to service on error

This commit is contained in:
Nodir Temirkhodjaev 2022-05-19 12:36:30 +03:00
parent 997d1c5d0e
commit 8fd43d1b1a
6 changed files with 72 additions and 22 deletions

View File

@ -21,6 +21,8 @@
namespace { namespace {
constexpr int maxClientsCount = 9;
const QLoggingCategory LC("control"); const QLoggingCategory LC("control");
} }
@ -52,9 +54,9 @@ ControlWorker *ControlManager::newServiceClient(QObject *parent) const
connect(w, &ControlWorker::requestReady, this, &ControlManager::processRequest); connect(w, &ControlWorker::requestReady, this, &ControlManager::processRequest);
if (!w->connectToServer(getServerName(true))) { w->setServerName(getServerName(/*isService=*/true));
qCWarning(LC) << "Server connect error:" << socket->state() << socket->errorString(); w->connectToServer();
}
return w; return w;
} }
@ -64,7 +66,7 @@ bool ControlManager::listen()
Q_ASSERT(!m_server); Q_ASSERT(!m_server);
m_server = new QLocalServer(this); m_server = new QLocalServer(this);
m_server->setMaxPendingConnections(3); m_server->setMaxPendingConnections(maxClientsCount);
m_server->setSocketOptions( m_server->setSocketOptions(
settings->isService() ? QLocalServer::WorldAccessOption : QLocalServer::NoOptions); settings->isService() ? QLocalServer::WorldAccessOption : QLocalServer::NoOptions);
@ -94,10 +96,9 @@ bool ControlManager::postCommand()
ControlWorker w(&socket); ControlWorker w(&socket);
// Connect to server // Connect to server
if (!w.connectToServer(getServerName())) { w.setServerName(getServerName(/*isService=*/false));
qCWarning(LC) << "Connect to server error:" << socket.errorString(); if (!w.connectToServer())
return false; return false;
}
// Send data // Send data
const QVariantList args = ControlWorker::buildArgs(settings->args()); const QVariantList args = ControlWorker::buildArgs(settings->args());
@ -110,9 +111,8 @@ bool ControlManager::postCommand()
void ControlManager::onNewConnection() void ControlManager::onNewConnection()
{ {
while (QLocalSocket *socket = m_server->nextPendingConnection()) { while (QLocalSocket *socket = m_server->nextPendingConnection()) {
constexpr int maxClientsCount = 9;
if (m_clients.size() > maxClientsCount) { if (m_clients.size() > maxClientsCount) {
qCDebug(LC) << "Client dropped"; qCDebug(LC) << "Client dropped: Count limit";
delete socket; delete socket;
continue; continue;
} }

View File

@ -76,7 +76,11 @@ bool parseArgsData(const QByteArray &buffer, QVariantList &args, bool compressed
} }
ControlWorker::ControlWorker(QLocalSocket *socket, QObject *parent) : ControlWorker::ControlWorker(QLocalSocket *socket, QObject *parent) :
QObject(parent), m_isServiceClient(false), m_isClientValidated(false), m_socket(socket) QObject(parent),
m_isServiceClient(false),
m_isClientValidated(false),
m_isTryReconnect(false),
m_socket(socket)
{ {
} }
@ -99,19 +103,35 @@ void ControlWorker::setupForAsync()
{ {
socket()->setParent(this); socket()->setParent(this);
connect(socket(), &QLocalSocket::disconnected, this, &ControlWorker::disconnected);
connect(socket(), &QLocalSocket::errorOccurred, this, connect(socket(), &QLocalSocket::errorOccurred, this,
[&](QLocalSocket::LocalSocketError socketError) { [&](QLocalSocket::LocalSocketError socketError) {
qCWarning(LC) << "Client error:" << id() << socketError << errorString(); qCWarning(LC) << "Client error:" << id() << socketError << errorString();
close(); close();
}); });
connect(socket(), &QLocalSocket::disconnected, this, &ControlWorker::onDisconnected);
connect(socket(), &QLocalSocket::readyRead, this, &ControlWorker::processRequest); connect(socket(), &QLocalSocket::readyRead, this, &ControlWorker::processRequest);
} }
bool ControlWorker::connectToServer(const QString &name) void ControlWorker::setServerName(const QString &name)
{ {
socket()->connectToServer(name); socket()->setServerName(name);
return socket()->waitForConnected(100) && socket()->state() == QLocalSocket::ConnectedState; }
bool ControlWorker::connectToServer()
{
socket()->connectToServer();
if (!socket()->waitForConnected(150)) {
qCWarning(LC) << "Connection error:" << socket()->state() << socket()->errorString();
return false;
}
if (socket()->state() != QLocalSocket::ConnectedState) {
qCWarning(LC) << "Connection state error:" << socket()->state();
return false;
}
return true;
} }
void ControlWorker::close() void ControlWorker::close()
@ -120,6 +140,14 @@ void ControlWorker::close()
socket()->close(); socket()->close();
} }
void ControlWorker::onDisconnected()
{
if (isTryReconnect() && connectToServer())
return;
emit disconnected();
}
QByteArray ControlWorker::buildCommandData(Control::Command command, const QVariantList &args) QByteArray ControlWorker::buildCommandData(Control::Command command, const QVariantList &args)
{ {
QByteArray data; QByteArray data;

View File

@ -21,6 +21,9 @@ public:
bool isClientValidated() const { return m_isClientValidated; } bool isClientValidated() const { return m_isClientValidated; }
void setIsClientValidated(bool v) { m_isClientValidated = v; } void setIsClientValidated(bool v) { m_isClientValidated = v; }
bool isTryReconnect() const { return m_isTryReconnect; }
void setIsTryReconnect(bool v) { m_isTryReconnect = v; }
QLocalSocket *socket() const { return m_socket; } QLocalSocket *socket() const { return m_socket; }
int id() const; int id() const;
@ -29,7 +32,8 @@ public:
void setupForAsync(); void setupForAsync();
bool connectToServer(const QString &name); void setServerName(const QString &name);
bool connectToServer();
static QByteArray buildCommandData(Control::Command command, const QVariantList &args = {}); static QByteArray buildCommandData(Control::Command command, const QVariantList &args = {});
bool sendCommandData(const QByteArray &commandData); bool sendCommandData(const QByteArray &commandData);
@ -49,6 +53,7 @@ public slots:
void close(); void close();
private slots: private slots:
void onDisconnected();
void processRequest(); void processRequest();
private: private:
@ -86,6 +91,7 @@ protected:
private: private:
bool m_isServiceClient : 1; bool m_isServiceClient : 1;
bool m_isClientValidated : 1; bool m_isClientValidated : 1;
bool m_isTryReconnect : 1;
RequestHeader m_requestHeader; RequestHeader m_requestHeader;
QByteArray m_requestBuffer; QByteArray m_requestBuffer;

View File

@ -30,8 +30,6 @@ bool DriverManagerRpc::openDevice()
bool DriverManagerRpc::closeDevice() bool DriverManagerRpc::closeDevice()
{ {
IoC<RpcManager>()->client()->close();
updateState(0, false); updateState(0, false);
return false; return false;

View File

@ -259,6 +259,11 @@ void RpcManager::setUp()
} }
} }
void RpcManager::tearDown()
{
closeClient();
}
void RpcManager::setupServerSignals() void RpcManager::setupServerSignals()
{ {
setupAppInfoManagerSignals(); setupAppInfoManagerSignals();
@ -363,9 +368,20 @@ void RpcManager::setupClient()
auto controlManager = IoC()->setUpDependency<ControlManager>(); auto controlManager = IoC()->setUpDependency<ControlManager>();
m_client = controlManager->newServiceClient(this); m_client = controlManager->newServiceClient(this);
client()->setIsTryReconnect(true);
invokeOnServer(Control::Rpc_RpcManager_initClient); invokeOnServer(Control::Rpc_RpcManager_initClient);
} }
void RpcManager::closeClient()
{
if (!client())
return;
client()->setIsTryReconnect(false);
client()->close();
}
bool RpcManager::waitResult() bool RpcManager::waitResult()
{ {
m_resultCommand = Control::CommandNone; m_resultCommand = Control::CommandNone;
@ -384,17 +400,17 @@ void RpcManager::sendResult(ControlWorker *w, bool ok, const QVariantList &args)
} }
bool RpcManager::invokeOnServer(Control::Command cmd, const QVariantList &args) bool RpcManager::invokeOnServer(Control::Command cmd, const QVariantList &args)
{
return client()->sendCommand(cmd, args);
}
bool RpcManager::doOnServer(Control::Command cmd, const QVariantList &args, QVariantList *resArgs)
{ {
if (!client()->isConnected()) { if (!client()->isConnected()) {
IoC<WindowManager>()->showErrorBox(tr("Service isn't available.")); IoC<WindowManager>()->showErrorBox(tr("Service isn't available."));
return false; return false;
} }
return client()->sendCommand(cmd, args);
}
bool RpcManager::doOnServer(Control::Command cmd, const QVariantList &args, QVariantList *resArgs)
{
if (!invokeOnServer(cmd, args)) if (!invokeOnServer(cmd, args))
return false; return false;

View File

@ -23,6 +23,7 @@ public:
ControlWorker *client() const { return m_client; } ControlWorker *client() const { return m_client; }
void setUp() override; void setUp() override;
void tearDown() override;
bool waitResult(); bool waitResult();
void sendResult(ControlWorker *w, bool ok, const QVariantList &args = {}); void sendResult(ControlWorker *w, bool ok, const QVariantList &args = {});
@ -43,6 +44,7 @@ private:
void setupTaskManagerSignals(); void setupTaskManagerSignals();
void setupClient(); void setupClient();
void closeClient();
void invokeOnClients(Control::Command cmd, const QVariantList &args = {}); void invokeOnClients(Control::Command cmd, const QVariantList &args = {});