refactor: Make connection more async (#182)

This commit is contained in:
Petr Mironychev 2025-05-01 15:35:33 +02:00 committed by GitHub
parent 4e05abc7d2
commit 25a6983de0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 96 additions and 28 deletions

View File

@ -57,6 +57,17 @@ LLMClientInterface::LLMClientInterface(
&LLMCore::RequestHandler::completionReceived,
this,
&LLMClientInterface::sendCompletionToClient);
// TODO handle error
// connect(
// &m_requestHandler,
// &LLMCore::RequestHandler::requestFinished,
// this,
// [this](const QString &, bool success, const QString &errorString) {
// if (!success) {
// emit error(errorString);
// }
// });
}
Utils::FilePath LLMClientInterface::serverDeviceTemplate() const

View File

@ -22,14 +22,51 @@
#include <QJsonDocument>
#include <QNetworkReply>
#include <QThread>
namespace QodeAssist::LLMCore {
RequestHandler::RequestHandler(QObject *parent)
: RequestHandlerBase(parent)
{}
, m_manager(new QNetworkAccessManager(this))
{
connect(
this,
&RequestHandler::doSendRequest,
this,
&RequestHandler::sendLLMRequestInternal,
Qt::QueuedConnection);
connect(
this,
&RequestHandler::doCancelRequest,
this,
&RequestHandler::cancelRequestInternal,
Qt::QueuedConnection);
}
RequestHandler::~RequestHandler()
{
for (auto reply : m_activeRequests) {
reply->abort();
reply->deleteLater();
}
m_activeRequests.clear();
m_accumulatedResponses.clear();
}
void RequestHandler::sendLLMRequest(const LLMConfig &config, const QJsonObject &request)
{
emit doSendRequest(config, request);
}
bool RequestHandler::cancelRequest(const QString &id)
{
emit doCancelRequest(id);
return true;
}
void RequestHandler::sendLLMRequestInternal(const LLMConfig &config, const QJsonObject &request)
{
LOG_MESSAGE(QString("Sending request to llm: \nurl: %1\nRequest body:\n%2")
.arg(
@ -37,12 +74,13 @@ void RequestHandler::sendLLMRequest(const LLMConfig &config, const QJsonObject &
QString::fromUtf8(
QJsonDocument(config.providerRequest).toJson(QJsonDocument::Indented))));
QNetworkAccessManager *manager = new QNetworkAccessManager();
QNetworkRequest networkRequest(config.url);
networkRequest.setTransferTimeout(300000);
config.provider->prepareNetworkRequest(networkRequest);
QNetworkReply *reply
= manager->post(networkRequest, QJsonDocument(config.providerRequest).toJson());
= m_manager->post(networkRequest, QJsonDocument(config.providerRequest).toJson());
if (!reply) {
LOG_MESSAGE("Error: Failed to create network reply");
return;
@ -55,24 +93,28 @@ void RequestHandler::sendLLMRequest(const LLMConfig &config, const QJsonObject &
handleLLMResponse(reply, request, config);
});
connect(reply, &QNetworkReply::finished, this, [this, reply, requestId, manager]() {
m_activeRequests.remove(requestId);
if (reply->error() != QNetworkReply::NoError) {
QString errorMessage = reply->errorString();
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
connect(
reply,
&QNetworkReply::finished,
this,
[this, reply, requestId]() {
m_activeRequests.remove(requestId);
if (reply->error() != QNetworkReply::NoError) {
QString errorMessage = reply->errorString();
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
LOG_MESSAGE(
QString("Error details: %1\nStatus code: %2").arg(errorMessage).arg(statusCode));
LOG_MESSAGE(
QString("Error details: %1\nStatus code: %2").arg(errorMessage).arg(statusCode));
emit requestFinished(requestId, false, errorMessage);
} else {
LOG_MESSAGE("Request finished successfully");
emit requestFinished(requestId, true, QString());
}
emit requestFinished(requestId, false, errorMessage);
} else {
LOG_MESSAGE("Request finished successfully");
emit requestFinished(requestId, true, QString());
}
reply->deleteLater();
manager->deleteLater();
});
reply->deleteLater();
},
Qt::QueuedConnection);
}
void RequestHandler::handleLLMResponse(
@ -102,17 +144,18 @@ void RequestHandler::handleLLMResponse(
m_accumulatedResponses.remove(reply);
}
bool RequestHandler::cancelRequest(const QString &id)
void RequestHandler::cancelRequestInternal(const QString &id)
{
QMutexLocker locker(&m_mutex);
if (m_activeRequests.contains(id)) {
QNetworkReply *reply = m_activeRequests[id];
reply->abort();
m_activeRequests.remove(id);
m_accumulatedResponses.remove(reply);
locker.unlock();
emit requestCancelled(id);
return true;
}
return false;
}
bool RequestHandler::processSingleLineCompletion(

View File

@ -20,6 +20,7 @@
#pragma once
#include <QJsonObject>
#include <QMutex>
#include <QNetworkAccessManager>
#include <QObject>
@ -32,16 +33,32 @@ namespace QodeAssist::LLMCore {
class RequestHandler : public RequestHandlerBase
{
Q_OBJECT
public:
explicit RequestHandler(QObject *parent = nullptr);
~RequestHandler() override;
void sendLLMRequest(const LLMConfig &config, const QJsonObject &request) override;
bool cancelRequest(const QString &id) override;
void handleLLMResponse(QNetworkReply *reply, const QJsonObject &request, const LLMConfig &config);
signals:
void doSendRequest(QodeAssist::LLMCore::LLMConfig config, QJsonObject request);
void doCancelRequest(QString id);
private slots:
void sendLLMRequestInternal(
const QodeAssist::LLMCore::LLMConfig &config, const QJsonObject &request);
void cancelRequestInternal(const QString &id);
void handleLLMResponse(
QNetworkReply *reply,
const QJsonObject &request,
const QodeAssist::LLMCore::LLMConfig &config);
private:
QMap<QString, QNetworkReply *> m_activeRequests;
QMap<QNetworkReply *, QString> m_accumulatedResponses;
QNetworkAccessManager *m_manager;
QMutex m_mutex;
bool processSingleLineCompletion(
QNetworkReply *reply,

View File

@ -38,7 +38,6 @@ namespace QodeAssist {
void CompletionProgressHandler::showProgress(TextEditor::TextEditorWidget *widget)
{
m_widget = widget;
m_isActive = true;
if (m_widget) {
const QRect cursorRect = m_widget->cursorRect(m_widget->textCursor());
@ -54,14 +53,13 @@ void CompletionProgressHandler::showProgress(TextEditor::TextEditorWidget *widge
void CompletionProgressHandler::hideProgress()
{
m_isActive = false;
Utils::ToolTip::hide();
Utils::ToolTip::hideImmediately();
}
void CompletionProgressHandler::identifyMatch(
TextEditor::TextEditorWidget *editorWidget, int pos, ReportPriority report)
{
if (!m_isActive || !editorWidget) {
if (!editorWidget) {
report(Priority_None);
return;
}
@ -72,7 +70,7 @@ void CompletionProgressHandler::identifyMatch(
void CompletionProgressHandler::operateTooltip(
TextEditor::TextEditorWidget *editorWidget, const QPoint &point)
{
if (!m_isActive || !editorWidget)
if (!editorWidget)
return;
auto progressWidget = new ProgressWidget(editorWidget);

View File

@ -38,7 +38,6 @@ protected:
private:
QPointer<TextEditor::TextEditorWidget> m_widget;
QPoint m_iconPosition;
bool m_isActive = false;
};
} // namespace QodeAssist