fix(wallet): coalesce reachability probes

This commit is contained in:
Ricardo Guilherme Schmidt 2026-07-17 20:03:33 -03:00
parent 5c2e4fe462
commit 969a98aa27
No known key found for this signature in database
GPG Key ID: 1396EA17DE132FFE
3 changed files with 59 additions and 10 deletions

View File

@ -284,13 +284,24 @@ void WalletController::checkReachability()
if (!m_state.isWalletOpen || m_state.sequencerAddress.isEmpty())
return;
const quint64 generation = ++m_reachabilityGeneration;
const QString endpoint = m_state.sequencerAddress;
if (m_reachabilityReply && endpoint == m_reachabilityEndpoint)
return;
const quint64 generation = ++m_reachabilityGeneration;
if (m_reachabilityReply)
m_reachabilityReply->abort();
QNetworkRequest request{QUrl(endpoint)};
request.setTransferTimeout(4000);
QNetworkReply* reply = m_network->get(request);
m_reachabilityReply = reply;
m_reachabilityEndpoint = endpoint;
connect(reply, &QNetworkReply::finished, this,
[this, reply, generation, endpoint]() {
if (m_reachabilityReply == reply) {
m_reachabilityReply = nullptr;
m_reachabilityEndpoint.clear();
}
if (!m_state.isWalletOpen
|| generation != m_reachabilityGeneration
|| endpoint != m_state.sequencerAddress) {

View File

@ -6,6 +6,7 @@
#include "WalletProvider.h"
class QNetworkAccessManager;
class QNetworkReply;
class QTimer;
class WalletAccountModel;
@ -70,6 +71,8 @@ private:
WalletUiState m_state;
WalletAccountModel* m_accountModel;
QNetworkAccessManager* m_network;
QNetworkReply* m_reachabilityReply = nullptr;
QString m_reachabilityEndpoint;
QTimer* m_reachabilityTimer;
bool m_started = false;
quint64 m_operationGeneration = 0;

View File

@ -69,6 +69,7 @@ private slots:
void completedAsyncSnapshotReleasesCallback();
void deferredCallbacksIgnoreDestroyedController();
void newerReachabilityResultWins();
void coalescesReachabilityChecksForSameEndpoint();
};
void LogosWalletProviderTest::adoptsOpenWalletAndCachesSnapshots()
@ -540,27 +541,32 @@ void LogosWalletProviderTest::newerReachabilityResultWins()
QSettings settings(QStringLiteral("Logos"), settingsApplication);
settings.clear();
QTcpServer server;
QVERIFY(server.listen(QHostAddress::LocalHost));
const QString endpoint = QStringLiteral("http://127.0.0.1:%1").arg(server.serverPort());
QTcpServer firstServer;
QTcpServer secondServer;
QVERIFY(firstServer.listen(QHostAddress::LocalHost));
QVERIFY(secondServer.listen(QHostAddress::LocalHost));
const QString firstEndpoint = QStringLiteral("http://127.0.0.1:%1")
.arg(firstServer.serverPort());
const QString secondEndpoint = QStringLiteral("http://127.0.0.1:%1")
.arg(secondServer.serverPort());
FakeWalletProvider provider;
provider.connectResult.snapshot.sequencerAddress = endpoint;
provider.connectResult.snapshot.sequencerAddress = firstEndpoint;
WalletController controller(provider, settingsApplication);
auto* network = controller.findChild<QNetworkAccessManager*>();
QVERIFY(network);
QSignalSpy finished(network, &QNetworkAccessManager::finished);
QVERIFY(controller.open());
QTRY_VERIFY(server.hasPendingConnections());
QTcpSocket* first = server.nextPendingConnection();
QTRY_VERIFY(firstServer.hasPendingConnections());
QTcpSocket* first = firstServer.nextPendingConnection();
QVERIFY(first);
provider.createAccountResult.accountId = ACCOUNT_B;
provider.createAccountResult.snapshot.sequencerAddress = endpoint;
provider.createAccountResult.snapshot.sequencerAddress = secondEndpoint;
QCOMPARE(controller.createAccount(true), ACCOUNT_B);
QTRY_VERIFY(server.hasPendingConnections());
QTcpSocket* second = server.nextPendingConnection();
QTRY_VERIFY(secondServer.hasPendingConnections());
QTcpSocket* second = secondServer.nextPendingConnection();
QVERIFY(second);
second->write("HTTP/1.1 200 OK\r\nContent-Length: 0\r\nConnection: close\r\n\r\n");
@ -574,6 +580,35 @@ void LogosWalletProviderTest::newerReachabilityResultWins()
settings.clear();
}
void LogosWalletProviderTest::coalescesReachabilityChecksForSameEndpoint()
{
const QString settingsApplication = QStringLiteral("WalletReachabilityCoalesceTest");
QSettings settings(QStringLiteral("Logos"), settingsApplication);
settings.clear();
QTcpServer server;
QVERIFY(server.listen(QHostAddress::LocalHost));
const QString endpoint = QStringLiteral("http://127.0.0.1:%1").arg(server.serverPort());
FakeWalletProvider provider;
provider.connectResult.snapshot.sequencerAddress = endpoint;
WalletController controller(provider, settingsApplication);
QVERIFY(controller.open());
QTRY_VERIFY(server.hasPendingConnections());
QTcpSocket* request = server.nextPendingConnection();
QVERIFY(request);
provider.createAccountResult.accountId = ACCOUNT_B;
provider.createAccountResult.snapshot.sequencerAddress = endpoint;
QCOMPARE(controller.createAccount(true), ACCOUNT_B);
QTest::qWait(50);
QVERIFY(!server.hasPendingConnections());
request->write("HTTP/1.1 200 OK\r\nContent-Length: 0\r\nConnection: close\r\n\r\n");
request->disconnectFromHost();
settings.clear();
}
QTEST_GUILESS_MAIN(LogosWalletProviderTest)
#include "LogosWalletProviderTest.moc"