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

View File

@ -76,7 +76,11 @@ bool parseArgsData(const QByteArray &buffer, QVariantList &args, bool compressed
}
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);
connect(socket(), &QLocalSocket::disconnected, this, &ControlWorker::disconnected);
connect(socket(), &QLocalSocket::errorOccurred, this,
[&](QLocalSocket::LocalSocketError socketError) {
qCWarning(LC) << "Client error:" << id() << socketError << errorString();
close();
});
connect(socket(), &QLocalSocket::disconnected, this, &ControlWorker::onDisconnected);
connect(socket(), &QLocalSocket::readyRead, this, &ControlWorker::processRequest);
}
bool ControlWorker::connectToServer(const QString &name)
void ControlWorker::setServerName(const QString &name)
{
socket()->connectToServer(name);
return socket()->waitForConnected(100) && socket()->state() == QLocalSocket::ConnectedState;
socket()->setServerName(name);
}
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()
@ -120,6 +140,14 @@ void ControlWorker::close()
socket()->close();
}
void ControlWorker::onDisconnected()
{
if (isTryReconnect() && connectToServer())
return;
emit disconnected();
}
QByteArray ControlWorker::buildCommandData(Control::Command command, const QVariantList &args)
{
QByteArray data;

View File

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

View File

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

View File

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

View File

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