mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-09-23 01:55:10 -07:00
[DeckShare] Time the share-list round trip and backstop silently-destroyed intent chains
This commit is contained in:
parent
668b8ab931
commit
116c79802f
4 changed files with 34 additions and 2 deletions
|
|
@ -43,7 +43,11 @@ bool IntentOpenSharedDeck::checkPrecondition() const
|
||||||
void IntentOpenSharedDeck::onPreconditionSatisfied()
|
void IntentOpenSharedDeck::onPreconditionSatisfied()
|
||||||
{
|
{
|
||||||
// Resolve the share token to its items first; a share can contain more than
|
// Resolve the share token to its items first; a share can contain more than
|
||||||
// one deck, and each item is downloaded by id.
|
// one deck, and each item is downloaded by id. Time the round trip like the
|
||||||
|
// downloads, so a silent server cannot hang the chain forever.
|
||||||
|
listPhase = true;
|
||||||
|
downloadTimer->start();
|
||||||
|
|
||||||
Command_DeckShareList cmd;
|
Command_DeckShareList cmd;
|
||||||
cmd.set_token(context->shareToken.toStdString());
|
cmd.set_token(context->shareToken.toStdString());
|
||||||
|
|
||||||
|
|
@ -59,6 +63,9 @@ void IntentOpenSharedDeck::onPreconditionNotSatisfied()
|
||||||
|
|
||||||
void IntentOpenSharedDeck::listShareFinished(const Response &response, const CommandContainer & /* commandContainer */)
|
void IntentOpenSharedDeck::listShareFinished(const Response &response, const CommandContainer & /* commandContainer */)
|
||||||
{
|
{
|
||||||
|
downloadTimer->stop();
|
||||||
|
listPhase = false;
|
||||||
|
|
||||||
if (response.response_code() != Response::RespOk) {
|
if (response.response_code() != Response::RespOk) {
|
||||||
emitFailed(tr("The shared deck could not be found or has expired"));
|
emitFailed(tr("The shared deck could not be found or has expired"));
|
||||||
return;
|
return;
|
||||||
|
|
@ -177,6 +184,12 @@ void IntentOpenSharedDeck::onItemFailure(const QString &reason)
|
||||||
|
|
||||||
void IntentOpenSharedDeck::onDownloadTimeout()
|
void IntentOpenSharedDeck::onDownloadTimeout()
|
||||||
{
|
{
|
||||||
|
// The list phase has no preview dialog yet to report progress into; fail the
|
||||||
|
// whole intent instead of letting the shared deck hang in limbo.
|
||||||
|
if (listPhase) {
|
||||||
|
emitFailed(tr("Timed out while loading the shared deck"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
onItemFailure(tr("Timed out while downloading the shared deck"));
|
onItemFailure(tr("Timed out while downloading the shared deck"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ private:
|
||||||
QMap<int, QString> itemNames;
|
QMap<int, QString> itemNames;
|
||||||
QList<int> pendingItemIds;
|
QList<int> pendingItemIds;
|
||||||
QList<LoadedDeck> loadedDecks;
|
QList<LoadedDeck> loadedDecks;
|
||||||
|
bool listPhase = true;
|
||||||
int currentItemId = 0;
|
int currentItemId = 0;
|
||||||
int totalItems = 0;
|
int totalItems = 0;
|
||||||
int completedItems = 0;
|
int completedItems = 0;
|
||||||
|
|
|
||||||
|
|
@ -313,6 +313,10 @@ void IntentUrlParser::startNextChain()
|
||||||
connect(finalIntent, &Intent::finished, this, [this]() { chainEnded(true); });
|
connect(finalIntent, &Intent::finished, this, [this]() { chainEnded(true); });
|
||||||
connect(finalIntent, &Intent::failed, this, [this]() { chainEnded(false); });
|
connect(finalIntent, &Intent::failed, this, [this]() { chainEnded(false); });
|
||||||
connect(finalIntent, &Intent::cancelled, this, [this]() { chainEnded(false); });
|
connect(finalIntent, &Intent::cancelled, this, [this]() { chainEnded(false); });
|
||||||
|
// Backstop: if the final intent is destroyed without emitting a terminal
|
||||||
|
// signal (e.g. a network error dropped it while running), end the chain so
|
||||||
|
// later links are not queued and dropped for the rest of the session.
|
||||||
|
chainBackstopConnection = connect(finalIntent, &QObject::destroyed, this, &IntentUrlParser::onChainIntentDestroyed);
|
||||||
|
|
||||||
chain.intents.first()->execute();
|
chain.intents.first()->execute();
|
||||||
}
|
}
|
||||||
|
|
@ -320,6 +324,7 @@ void IntentUrlParser::startNextChain()
|
||||||
void IntentUrlParser::chainEnded(bool chainSucceeded)
|
void IntentUrlParser::chainEnded(bool chainSucceeded)
|
||||||
{
|
{
|
||||||
chainRunning = false;
|
chainRunning = false;
|
||||||
|
QObject::disconnect(chainBackstopConnection);
|
||||||
|
|
||||||
const PendingIntentChain chain = pendingChains.takeFirst();
|
const PendingIntentChain chain = pendingChains.takeFirst();
|
||||||
|
|
||||||
|
|
@ -338,6 +343,15 @@ void IntentUrlParser::chainEnded(bool chainSucceeded)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IntentUrlParser::onChainIntentDestroyed()
|
||||||
|
{
|
||||||
|
if (!chainRunning) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
qCWarning(UrlParserLog) << "Share-link intent destroyed without a terminal signal; ending its chain";
|
||||||
|
chainEnded(false);
|
||||||
|
}
|
||||||
|
|
||||||
void IntentUrlParser::restorePreviousServer(const PendingIntentChain &chain)
|
void IntentUrlParser::restorePreviousServer(const PendingIntentChain &chain)
|
||||||
{
|
{
|
||||||
if (chain.previousServerHost.isEmpty()) {
|
if (chain.previousServerHost.isEmpty()) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#ifndef COCKATRICE_URL_PARSER_H
|
#ifndef COCKATRICE_URL_PARSER_H
|
||||||
#define COCKATRICE_URL_PARSER_H
|
#define COCKATRICE_URL_PARSER_H
|
||||||
|
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QUrlQuery>
|
#include <QUrlQuery>
|
||||||
|
|
@ -29,7 +30,6 @@ struct PendingIntentChain
|
||||||
QString migrationTargetHost;
|
QString migrationTargetHost;
|
||||||
QString migrationTargetPort;
|
QString migrationTargetPort;
|
||||||
bool pendingRestore = false;
|
bool pendingRestore = false;
|
||||||
bool succeeded = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -60,12 +60,16 @@ private:
|
||||||
[[nodiscard]] bool isConnectedTo(const QString &hostname, const QString &port) const;
|
[[nodiscard]] bool isConnectedTo(const QString &hostname, const QString &port) const;
|
||||||
void startNextChain();
|
void startNextChain();
|
||||||
void chainEnded(bool chainSucceeded);
|
void chainEnded(bool chainSucceeded);
|
||||||
|
void onChainIntentDestroyed();
|
||||||
void restorePreviousServer(const PendingIntentChain &chain);
|
void restorePreviousServer(const PendingIntentChain &chain);
|
||||||
void restoreToPreviousServer(const PendingIntentChain &chain);
|
void restoreToPreviousServer(const PendingIntentChain &chain);
|
||||||
|
|
||||||
MainWindow *mainWindow;
|
MainWindow *mainWindow;
|
||||||
QList<PendingIntentChain> pendingChains;
|
QList<PendingIntentChain> pendingChains;
|
||||||
bool chainRunning = false;
|
bool chainRunning = false;
|
||||||
|
// Disconnects the destroyed-signal backstop once a chain ends, so an old
|
||||||
|
// intent's deferred deletion cannot end the chain that runs after it.
|
||||||
|
QMetaObject::Connection chainBackstopConnection;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // COCKATRICE_URL_PARSER_H
|
#endif // COCKATRICE_URL_PARSER_H
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue