mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-21 22:24:07 +01:00
feat: add a finally
callback to NetworkRequests (#2350)
Co-authored-by: Rasmus Karlsson <rasmus.karlsson@pajlada.com>
This commit is contained in:
parent
f19cc60a5b
commit
0542b81a03
6 changed files with 186 additions and 1 deletions
|
@ -12,6 +12,7 @@ class NetworkResult;
|
||||||
using NetworkSuccessCallback = std::function<Outcome(NetworkResult)>;
|
using NetworkSuccessCallback = std::function<Outcome(NetworkResult)>;
|
||||||
using NetworkErrorCallback = std::function<void(NetworkResult)>;
|
using NetworkErrorCallback = std::function<void(NetworkResult)>;
|
||||||
using NetworkReplyCreatedCallback = std::function<void(QNetworkReply *)>;
|
using NetworkReplyCreatedCallback = std::function<void(QNetworkReply *)>;
|
||||||
|
using NetworkFinallyCallback = std::function<void()>;
|
||||||
|
|
||||||
enum class NetworkRequestType {
|
enum class NetworkRequestType {
|
||||||
Get,
|
Get,
|
||||||
|
|
|
@ -132,6 +132,7 @@ void loadUncached(const std::shared_ptr<NetworkData> &data)
|
||||||
data->timer_, &QTimer::timeout, worker, [reply, data]() {
|
data->timer_, &QTimer::timeout, worker, [reply, data]() {
|
||||||
qCDebug(chatterinoCommon) << "Aborted!";
|
qCDebug(chatterinoCommon) << "Aborted!";
|
||||||
reply->abort();
|
reply->abort();
|
||||||
|
|
||||||
if (data->onError_)
|
if (data->onError_)
|
||||||
{
|
{
|
||||||
postToThread([data] {
|
postToThread([data] {
|
||||||
|
@ -139,6 +140,13 @@ void loadUncached(const std::shared_ptr<NetworkData> &data)
|
||||||
{}, NetworkResult::timedoutStatus));
|
{}, NetworkResult::timedoutStatus));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data->finally_)
|
||||||
|
{
|
||||||
|
postToThread([data] {
|
||||||
|
data->finally_();
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,17 +167,26 @@ void loadUncached(const std::shared_ptr<NetworkData> &data)
|
||||||
if (reply->error() ==
|
if (reply->error() ==
|
||||||
QNetworkReply::NetworkError::OperationCanceledError)
|
QNetworkReply::NetworkError::OperationCanceledError)
|
||||||
{
|
{
|
||||||
//operation cancelled, most likely timed out
|
// Operation cancelled, most likely timed out
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->onError_)
|
if (data->onError_)
|
||||||
{
|
{
|
||||||
auto status = reply->attribute(
|
auto status = reply->attribute(
|
||||||
QNetworkRequest::HttpStatusCodeAttribute);
|
QNetworkRequest::HttpStatusCodeAttribute);
|
||||||
|
// TODO: Should this always be run on the GUI thread?
|
||||||
postToThread([data, code = status.toInt()] {
|
postToThread([data, code = status.toInt()] {
|
||||||
data->onError_(NetworkResult({}, code));
|
data->onError_(NetworkResult({}, code));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data->finally_)
|
||||||
|
{
|
||||||
|
postToThread([data] {
|
||||||
|
data->finally_();
|
||||||
|
});
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,6 +213,16 @@ void loadUncached(const std::shared_ptr<NetworkData> &data)
|
||||||
// log("finished {}", data->request_.url().toString());
|
// log("finished {}", data->request_.url().toString());
|
||||||
|
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
|
|
||||||
|
if (data->finally_)
|
||||||
|
{
|
||||||
|
if (data->executeConcurrently_)
|
||||||
|
QtConcurrent::run([finally = std::move(data->finally_)] {
|
||||||
|
finally();
|
||||||
|
});
|
||||||
|
else
|
||||||
|
data->finally_();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (data->timer_ != nullptr)
|
if (data->timer_ != nullptr)
|
||||||
|
@ -271,6 +298,30 @@ void loadCached(const std::shared_ptr<NetworkData> &data)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data->finally_)
|
||||||
|
{
|
||||||
|
if (data->executeConcurrently_ || isGuiThread())
|
||||||
|
{
|
||||||
|
if (data->hasCaller_ && !data->caller_.get())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->finally_();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
postToThread([data]() {
|
||||||
|
if (data->hasCaller_ && !data->caller_.get())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->finally_();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@ struct NetworkData {
|
||||||
NetworkReplyCreatedCallback onReplyCreated_;
|
NetworkReplyCreatedCallback onReplyCreated_;
|
||||||
NetworkErrorCallback onError_;
|
NetworkErrorCallback onError_;
|
||||||
NetworkSuccessCallback onSuccess_;
|
NetworkSuccessCallback onSuccess_;
|
||||||
|
NetworkFinallyCallback finally_;
|
||||||
|
|
||||||
NetworkRequestType requestType_ = NetworkRequestType::Get;
|
NetworkRequestType requestType_ = NetworkRequestType::Get;
|
||||||
|
|
||||||
|
|
|
@ -79,6 +79,12 @@ NetworkRequest NetworkRequest::onSuccess(NetworkSuccessCallback cb) &&
|
||||||
return std::move(*this);
|
return std::move(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetworkRequest NetworkRequest::finally(NetworkFinallyCallback cb) &&
|
||||||
|
{
|
||||||
|
this->data->finally_ = cb;
|
||||||
|
return std::move(*this);
|
||||||
|
}
|
||||||
|
|
||||||
NetworkRequest NetworkRequest::header(const char *headerName,
|
NetworkRequest NetworkRequest::header(const char *headerName,
|
||||||
const char *value) &&
|
const char *value) &&
|
||||||
{
|
{
|
||||||
|
|
|
@ -42,6 +42,7 @@ public:
|
||||||
NetworkRequest onReplyCreated(NetworkReplyCreatedCallback cb) &&;
|
NetworkRequest onReplyCreated(NetworkReplyCreatedCallback cb) &&;
|
||||||
NetworkRequest onError(NetworkErrorCallback cb) &&;
|
NetworkRequest onError(NetworkErrorCallback cb) &&;
|
||||||
NetworkRequest onSuccess(NetworkSuccessCallback cb) &&;
|
NetworkRequest onSuccess(NetworkSuccessCallback cb) &&;
|
||||||
|
NetworkRequest finally(NetworkFinallyCallback cb) &&;
|
||||||
|
|
||||||
NetworkRequest payload(const QByteArray &payload) &&;
|
NetworkRequest payload(const QByteArray &payload) &&;
|
||||||
NetworkRequest cache() &&;
|
NetworkRequest cache() &&;
|
||||||
|
|
|
@ -67,6 +67,44 @@ TEST(NetworkRequest, Success)
|
||||||
EXPECT_TRUE(NetworkManager::workerThread.isRunning());
|
EXPECT_TRUE(NetworkManager::workerThread.isRunning());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(NetworkRequest, FinallyCallbackOnSuccess)
|
||||||
|
{
|
||||||
|
const std::vector<int> codes{200, 201, 202, 203, 204, 205, 206};
|
||||||
|
|
||||||
|
EXPECT_TRUE(NetworkManager::workerThread.isRunning());
|
||||||
|
|
||||||
|
for (const auto code : codes)
|
||||||
|
{
|
||||||
|
auto url = getStatusURL(code);
|
||||||
|
std::mutex mut;
|
||||||
|
bool requestDone = false;
|
||||||
|
std::condition_variable requestDoneCondition;
|
||||||
|
|
||||||
|
bool finallyCalled = false;
|
||||||
|
|
||||||
|
NetworkRequest(url)
|
||||||
|
.finally(
|
||||||
|
[&mut, &requestDone, &requestDoneCondition, &finallyCalled] {
|
||||||
|
finallyCalled = true;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::unique_lock lck(mut);
|
||||||
|
requestDone = true;
|
||||||
|
}
|
||||||
|
requestDoneCondition.notify_one();
|
||||||
|
})
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
// Wait for the request to finish
|
||||||
|
std::unique_lock lck(mut);
|
||||||
|
requestDoneCondition.wait(lck, [&requestDone] {
|
||||||
|
return requestDone;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXPECT_TRUE(finallyCalled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST(NetworkRequest, Error)
|
TEST(NetworkRequest, Error)
|
||||||
{
|
{
|
||||||
const std::vector<int> codes{
|
const std::vector<int> codes{
|
||||||
|
@ -118,6 +156,47 @@ TEST(NetworkRequest, Error)
|
||||||
EXPECT_TRUE(NetworkManager::workerThread.isRunning());
|
EXPECT_TRUE(NetworkManager::workerThread.isRunning());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(NetworkRequest, FinallyCallbackOnError)
|
||||||
|
{
|
||||||
|
const std::vector<int> codes{
|
||||||
|
400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410,
|
||||||
|
411, 412, 413, 414, 418, 500, 501, 502, 503, 504,
|
||||||
|
};
|
||||||
|
|
||||||
|
EXPECT_TRUE(NetworkManager::workerThread.isRunning());
|
||||||
|
|
||||||
|
for (const auto code : codes)
|
||||||
|
{
|
||||||
|
auto url = getStatusURL(code);
|
||||||
|
std::mutex mut;
|
||||||
|
bool requestDone = false;
|
||||||
|
std::condition_variable requestDoneCondition;
|
||||||
|
|
||||||
|
bool finallyCalled = false;
|
||||||
|
|
||||||
|
NetworkRequest(url)
|
||||||
|
.finally(
|
||||||
|
[&mut, &requestDone, &requestDoneCondition, &finallyCalled] {
|
||||||
|
finallyCalled = true;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::unique_lock lck(mut);
|
||||||
|
requestDone = true;
|
||||||
|
}
|
||||||
|
requestDoneCondition.notify_one();
|
||||||
|
})
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
// Wait for the request to finish
|
||||||
|
std::unique_lock lck(mut);
|
||||||
|
requestDoneCondition.wait(lck, [&requestDone] {
|
||||||
|
return requestDone;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXPECT_TRUE(finallyCalled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST(NetworkRequest, TimeoutTimingOut)
|
TEST(NetworkRequest, TimeoutTimingOut)
|
||||||
{
|
{
|
||||||
EXPECT_TRUE(NetworkManager::workerThread.isRunning());
|
EXPECT_TRUE(NetworkManager::workerThread.isRunning());
|
||||||
|
@ -209,3 +288,49 @@ TEST(NetworkRequest, TimeoutNotTimingOut)
|
||||||
|
|
||||||
EXPECT_TRUE(NetworkManager::workerThread.isRunning());
|
EXPECT_TRUE(NetworkManager::workerThread.isRunning());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(NetworkRequest, FinallyCallbackOnTimeout)
|
||||||
|
{
|
||||||
|
EXPECT_TRUE(NetworkManager::workerThread.isRunning());
|
||||||
|
|
||||||
|
auto url = "http://httpbin.org/delay/5";
|
||||||
|
|
||||||
|
std::mutex mut;
|
||||||
|
bool requestDone = false;
|
||||||
|
std::condition_variable requestDoneCondition;
|
||||||
|
bool finallyCalled = false;
|
||||||
|
bool onSuccessCalled = false;
|
||||||
|
bool onErrorCalled = false;
|
||||||
|
|
||||||
|
NetworkRequest(url)
|
||||||
|
.timeout(1000)
|
||||||
|
.onSuccess([&](NetworkResult result) -> Outcome {
|
||||||
|
onSuccessCalled = true;
|
||||||
|
return Success;
|
||||||
|
})
|
||||||
|
.onError([&](NetworkResult result) {
|
||||||
|
onErrorCalled = true;
|
||||||
|
EXPECT_EQ(result.status(), NetworkResult::timedoutStatus);
|
||||||
|
})
|
||||||
|
.finally([&] {
|
||||||
|
finallyCalled = true;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::unique_lock lck(mut);
|
||||||
|
requestDone = true;
|
||||||
|
}
|
||||||
|
requestDoneCondition.notify_one();
|
||||||
|
})
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
// Wait for the request to finish
|
||||||
|
std::unique_lock lck(mut);
|
||||||
|
requestDoneCondition.wait(lck, [&requestDone] {
|
||||||
|
return requestDone;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXPECT_TRUE(finallyCalled);
|
||||||
|
EXPECT_TRUE(onErrorCalled);
|
||||||
|
EXPECT_FALSE(onSuccessCalled);
|
||||||
|
EXPECT_TRUE(NetworkManager::workerThread.isRunning());
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue