[PublicDecks] Drop stale deck-list replies after the loading timeout

A reply that lands after its own loading timeout (the reverse of the ping
sweep dropping the command) could stop the newer request's timeout timer
and repaint the grid with out-of-date data. Each refresh now captures a
monotonically increasing request id, and only the newest request's reply
updates the grid.
This commit is contained in:
Lukas Brübach 2026-09-20 20:17:07 +02:00 committed by GitHub
parent cafc1df171
commit 2d15529d48
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 13 additions and 1 deletions

View file

@ -131,12 +131,23 @@ void RemotePublicDecksModel::refresh(const QString &userName)
if (loading) { if (loading) {
return; return;
} }
// Every refresh captures its own request id so a reply that lands after its
// loading timeout (the reverse of the ping sweep dropping the command) is
// recognised as stale: it must not stop the newer request's timer or paint
// the grid with out-of-date data.
const int seq = ++requestSequence;
setLoading(true); setLoading(true);
loadingTimeoutTimer->start(); loadingTimeoutTimer->start();
Command_DeckListOtherUser cmd; Command_DeckListOtherUser cmd;
cmd.set_user_name(userName.toStdString()); cmd.set_user_name(userName.toStdString());
PendingCommand *pend = client->prepareSessionCommand(cmd); PendingCommand *pend = client->prepareSessionCommand(cmd);
connect(pend, &PendingCommand::finished, this, &RemotePublicDecksModel::decksReceived); connect(pend, &PendingCommand::finished, this,
[this, seq](const Response &response, const CommandContainer &commandContainer) {
if (seq != requestSequence) {
return; // a newer refresh superseded this one
}
decksReceived(response, commandContainer);
});
client->sendCommand(pend); client->sendCommand(pend);
} }

View file

@ -117,6 +117,7 @@ private:
QList<DeckEntry> decks; QList<DeckEntry> decks;
QList<int> visibleIndices; ///< Row indices into `decks` that pass the current filters. QList<int> visibleIndices; ///< Row indices into `decks` that pass the current filters.
bool loading = false; bool loading = false;
int requestSequence = 0; ///< Monotonically increases per refresh; only the newest request may update the grid.
QString searchText; QString searchText;
VisualDeckStorageSortFilterProxyModel::FilterMode colorFilterMode = VisualDeckStorageSortFilterProxyModel::Includes; VisualDeckStorageSortFilterProxyModel::FilterMode colorFilterMode = VisualDeckStorageSortFilterProxyModel::Includes;