-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NetworkTask: Distinguish implicit abort by timeout from explicit abort #10884
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -205,11 +205,15 @@ void WebTask::slotStart(int timeoutMillis, int delayMillis) { | |
|
||
auto* const pNetworkAccessManager = m_networkAccessManagerWeakPtr.data(); | ||
VERIFY_OR_DEBUG_ASSERT(pNetworkAccessManager) { | ||
// Internally switch the state to pending as a prerequisite before | ||
// invoking onNetworkError(). This is only required for technical | ||
// reasons and the intermediate state will never become visible. | ||
m_state = State::Pending; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Setting the state to Pending here is just a hack to pass the debug assertion in onNetworkError(). The correct solution is to change the state to State::Failed after the previous call fails. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I disagree. |
||
onNetworkError( | ||
QNetworkReply::NetworkSessionFailedError, | ||
tr("No network access"), | ||
WebResponseWithContent{}); | ||
DEBUG_ASSERT(m_state == State::Failed); | ||
return; | ||
} | ||
DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(pNetworkAccessManager); | ||
|
@@ -256,7 +260,7 @@ void WebTask::slotStart(int timeoutMillis, int delayMillis) { | |
Qt::UniqueConnection); | ||
} | ||
|
||
void WebTask::slotAbort() { | ||
void WebTask::slotAbort(bool timedOut) { | ||
DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(this); | ||
if (!isBusy()) { | ||
DEBUG_ASSERT(m_timeoutTimerId == kInvalidTimerId); | ||
|
@@ -312,7 +316,7 @@ void WebTask::slotAbort() { | |
// this scope. | ||
const auto pendingNetworkReplyDeleter = ScopedDeleteLater(pPendingNetworkReply); | ||
m_pendingNetworkReplyWeakPtr.clear(); | ||
doNetworkReplyAborted(pPendingNetworkReply); | ||
doNetworkReplyAborted(pPendingNetworkReply, timedOut); | ||
} | ||
|
||
m_state = State::Aborted; | ||
|
@@ -348,7 +352,7 @@ void WebTask::timerEvent(QTimerEvent* event) { | |
<< "Aborting after timed out"; | ||
// Trigger the regular abort workflow after a client-side | ||
// timeout occurred | ||
slotAbort(); | ||
slotAbort(true); | ||
} | ||
|
||
void WebTask::slotNetworkReplyFinished() { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already have a code path to deliver timeouts to the calling code. Introducing here an anonymous boolean to pass a timeout a different way is unnecessary and raises the code complexity unnecessarily. In addition it exposes implementation details to the calling code. It violates also the code symmetry, because in case of all other error cause the error message is created in the NetworkTask and its derived classes all other Errors are passed in a generic way including a translated message and detailed error codes-
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is bikeshedding. I already wanted to mention that I was too lazy to introduce an
enum class
before getting feedback on the proposed solution. I assumed that this is obvious.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You still confuse client-side with server-side timeouts. A client-side timeout is an abort, but with an implicit instead of an explicit trigger. Technically, it is not an error, because the task did what you told it to do (according to the timeout parameter provided when starting it). A server-side timeout is an unexpected outcome and an error.
Aborting a request might subsequently let your business code fail. But that's a different level of abstraction.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seriously @uklotzde ? Please treat me with respect!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The client side timeout is an network error in the same way as the server side timeout. There is no need to pass one over a different signal than the other. In contrast the slotAbort is a direct responds to an explicit immediately abort request. Using that for a Network was wrong and causes the bug I have fixed.
But anyway this is an implementation detail f the bug fix.
You have not explained why you experience a bug with it.