LibresapiLocalClient fix delay on event coalescing

When the server reply to a burst of querys the socket readyRead() signal
  may be called only once, thus causing reply not being parsed until
  next event, and making the query queue grow with time and the user
  interface unusable, to fix this a the end of the read() slot if there
  is more data available in the socket read is called again to parse it
LibresapiLocalClient improved debugging that may be configured per
  instance in case of debug build
This commit is contained in:
Gioacchino Mazzurco 2017-04-03 21:09:12 +02:00
parent 6daa3f4f68
commit 286783c72e
2 changed files with 109 additions and 13 deletions

View File

@ -20,7 +20,7 @@
#include "libresapilocalclient.h" #include "libresapilocalclient.h"
#include <QJSEngine> #include <QJSEngine>
#include <QtDebug>
void LibresapiLocalClient::openConnection(QString socketPath) void LibresapiLocalClient::openConnection(QString socketPath)
{ {
@ -34,30 +34,94 @@ void LibresapiLocalClient::openConnection(QString socketPath)
int LibresapiLocalClient::request( const QString& path, const QString& jsonData, int LibresapiLocalClient::request( const QString& path, const QString& jsonData,
QJSValue callback ) QJSValue callback )
{ {
#ifdef QT_DEBUG
if(mDebug)
qDebug() << reqCount++ << __PRETTY_FUNCTION__ << path << jsonData
<< callback.toString();
#endif // QT_DEBUG
QByteArray data; QByteArray data;
data.append(path); data.append('\n'); data.append(path); data.append('\n');
data.append(jsonData); data.append('\n'); data.append(jsonData); data.append('\n');
callbackQueue.enqueue(callback); processingQueue.enqueue(PQRecord(path, jsonData, callback));
return mLocalSocket.write(data); return mLocalSocket.write(data);
} }
void LibresapiLocalClient::socketError(QLocalSocket::LocalSocketError) void LibresapiLocalClient::socketError(QLocalSocket::LocalSocketError)
{ {
qDebug() << "Socket Eerror!!" << mLocalSocket.errorString(); qCritical() << __PRETTY_FUNCTION__ << "Socket Eerror! "
<< mLocalSocket.errorString();
} }
void LibresapiLocalClient::read() void LibresapiLocalClient::read()
{ {
QString receivedMsg(mLocalSocket.readLine()); if(processingQueue.isEmpty())
QJSValue callback(callbackQueue.dequeue());
if(callback.isCallable())
{ {
QJSValue params = callback.engine()->newObject(); qCritical() << __PRETTY_FUNCTION__ << "callbackQueue is empty "
params.setProperty("response", receivedMsg); << "something really fishy is happening!";
return;
callback.call(QJSValueList { params });
} }
if(!mLocalSocket.canReadLine())
{
qWarning() << __PRETTY_FUNCTION__
<< "Strange, can't read a complete line!";
return;
}
QByteArray&& ba(mLocalSocket.readLine());
if(ba.size() < 2)
{
qWarning() << __PRETTY_FUNCTION__ << "Got answer of less then 2 bytes,"
<< "something fishy is happening!";
return;
}
QString receivedMsg(ba);
PQRecord&& p(processingQueue.dequeue());
#ifdef QT_DEBUG
if(mDebug)
qDebug() << ansCount++ << __PRETTY_FUNCTION__ << receivedMsg << p.mPath
<< p.mJsonData << p.mCallback.toString();
#endif // QT_DEBUG
emit goodResponseReceived(receivedMsg); /// @deprecated emit goodResponseReceived(receivedMsg); /// @deprecated
emit responseReceived(receivedMsg); emit responseReceived(receivedMsg);
if(p.mCallback.isCallable())
{
QJSValue&& params(p.mCallback.engine()->newObject());
params.setProperty("response", receivedMsg);
p.mCallback.call(QJSValueList { params });
}
// In case of multiple reply coaleshed in the same signal
if(mLocalSocket.bytesAvailable() > 0) read();
} }
LibresapiLocalClient::PQRecord::PQRecord( const QString&
#ifdef QT_DEBUG
path
#endif //QT_DEBUG
, const QString&
#ifdef QT_DEBUG
jsonData
#endif //QT_DEBUG
, const QJSValue& callback) :
#ifdef QT_DEBUG
mPath(path), mJsonData(jsonData),
#endif //QT_DEBUG
mCallback(callback) {}
#ifdef QT_DEBUG
void LibresapiLocalClient::setDebug(bool v)
{
if(v != mDebug)
{
mDebug = v;
emit debugChanged();
}
}
#endif // QT_DEBUG

View File

@ -29,15 +29,43 @@ class LibresapiLocalClient : public QObject
Q_OBJECT Q_OBJECT
public: public:
LibresapiLocalClient() : mLocalSocket(this) {} LibresapiLocalClient() :
#ifdef QT_DEBUG
reqCount(0), ansCount(0), mDebug(true),
#endif // QT_DEBUG
mLocalSocket(this) {}
Q_INVOKABLE int request( const QString& path, const QString& jsonData = "", Q_INVOKABLE int request( const QString& path, const QString& jsonData = "",
QJSValue callback = QJSValue::NullValue); QJSValue callback = QJSValue::NullValue );
Q_INVOKABLE void openConnection(QString socketPath); Q_INVOKABLE void openConnection(QString socketPath);
#ifdef QT_DEBUG
Q_PROPERTY(bool debug READ debug WRITE setDebug NOTIFY debugChanged)
bool debug() const { return mDebug; }
void setDebug(bool v);
uint64_t reqCount;
uint64_t ansCount;
bool mDebug;
#endif // QT_DEBUG
private: private:
QLocalSocket mLocalSocket; QLocalSocket mLocalSocket;
QQueue<QJSValue> callbackQueue;
struct PQRecord
{
PQRecord( const QString& path, const QString& jsonData,
const QJSValue& callback);
#ifdef QT_DEBUG
QString mPath;
QString mJsonData;
#endif //QT_DEBUG
QJSValue mCallback;
};
QQueue<PQRecord> processingQueue;
private slots: private slots:
void socketError(QLocalSocket::LocalSocketError error); void socketError(QLocalSocket::LocalSocketError error);
@ -52,6 +80,10 @@ signals:
* @param msg * @param msg
*/ */
void responseReceived(const QString & msg); void responseReceived(const QString & msg);
#ifdef QT_DEBUG
void debugChanged();
#endif // QT_DEBUG
}; };
#endif // LIBRESAPILOCALCLIENT_H #endif // LIBRESAPILOCALCLIENT_H