summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIvo van Dongen <info@ivovandongen.nl>2016-08-31 16:43:33 +0200
committerIvo van Dongen <info@ivovandongen.nl>2016-09-13 14:21:37 +0200
commit290bd07a92d7103c67f606c1423785069fc9b776 (patch)
tree00fa0a654830f3cf239932f266e311cab6ebeb59 /src
parentfdaf26b2c02afa6042876962f92b1eaf0ada19bb (diff)
downloadqtlocation-mapboxgl-290bd07a92d7103c67f606c1423785069fc9b776.tar.gz
[core] OnlineFileSource - rate limit
Diffstat (limited to 'src')
-rw-r--r--src/mbgl/storage/response.cpp6
-rw-r--r--src/mbgl/util/chrono.cpp4
-rw-r--r--src/mbgl/util/http_header.cpp20
-rw-r--r--src/mbgl/util/http_header.hpp3
-rw-r--r--src/mbgl/util/http_timeout.cpp40
-rw-r--r--src/mbgl/util/http_timeout.hpp15
6 files changed, 86 insertions, 2 deletions
diff --git a/src/mbgl/storage/response.cpp b/src/mbgl/storage/response.cpp
index 6809220166..a174339074 100644
--- a/src/mbgl/storage/response.cpp
+++ b/src/mbgl/storage/response.cpp
@@ -21,8 +21,8 @@ Response& Response::operator=(const Response& res) {
return *this;
}
-Response::Error::Error(Reason reason_, std::string message_)
- : reason(reason_), message(std::move(message_)) {
+Response::Error::Error(Reason reason_, std::string message_, optional<Timestamp> retryAfter_)
+ : reason(reason_), message(std::move(message_)), retryAfter(std::move(retryAfter_)) {
}
std::ostream& operator<<(std::ostream& os, Response::Error::Reason r) {
@@ -35,6 +35,8 @@ std::ostream& operator<<(std::ostream& os, Response::Error::Reason r) {
return os << "Response::Error::Reason::Server";
case Response::Error::Reason::Connection:
return os << "Response::Error::Reason::Connection";
+ case Response::Error::Reason::RateLimit:
+ return os << "Response::Error::Reason::RateLimit";
case Response::Error::Reason::Other:
return os << "Response::Error::Reason::Other";
}
diff --git a/src/mbgl/util/chrono.cpp b/src/mbgl/util/chrono.cpp
index 55b8a86e39..f338f524b9 100644
--- a/src/mbgl/util/chrono.cpp
+++ b/src/mbgl/util/chrono.cpp
@@ -33,6 +33,10 @@ std::string iso8601(Timestamp timestamp) {
Timestamp parseTimestamp(const char* timestamp) {
return std::chrono::time_point_cast<Seconds>(std::chrono::system_clock::from_time_t(parse_date(timestamp)));
}
+
+Timestamp parseTimestamp(const int32_t timestamp) {
+ return std::chrono::time_point_cast<Seconds>(std::chrono::system_clock::from_time_t(timestamp));
+}
} // namespace util
diff --git a/src/mbgl/util/http_header.cpp b/src/mbgl/util/http_header.cpp
index dceb331a3f..e337d4c8ab 100644
--- a/src/mbgl/util/http_header.cpp
+++ b/src/mbgl/util/http_header.cpp
@@ -28,6 +28,26 @@ CacheControl CacheControl::parse(const std::string& value) {
optional<Timestamp> CacheControl::toTimePoint() const {
return maxAge ? util::now() + Seconds(*maxAge) : optional<Timestamp>{};
}
+
+optional<Timestamp> parseRetryHeaders(const optional<std::string>& retryAfter,
+ const optional<std::string>& xRateLimitReset) {
+ if (retryAfter) {
+ try {
+ auto secs = std::chrono::seconds(std::stoi(*retryAfter));
+ return std::chrono::time_point_cast<Seconds>(std::chrono::system_clock::now() + secs);
+ } catch (...) {
+ return util::parseTimestamp((*retryAfter).c_str());
+ }
+ } else if (xRateLimitReset) {
+ try {
+ return util::parseTimestamp(std::stoi(*xRateLimitReset));
+ } catch (...) {
+ return {};
+ }
+ }
+
+ return {};
+}
} // namespace http
} // namespace mbgl
diff --git a/src/mbgl/util/http_header.hpp b/src/mbgl/util/http_header.hpp
index 8a83356977..fa76cb724e 100644
--- a/src/mbgl/util/http_header.hpp
+++ b/src/mbgl/util/http_header.hpp
@@ -17,6 +17,9 @@ public:
optional<Timestamp> toTimePoint() const;
};
+
+optional<Timestamp> parseRetryHeaders(const optional<std::string>& retryAfter,
+ const optional<std::string>& xRateLimitReset);
} // namespace http
} // namespace mbgl
diff --git a/src/mbgl/util/http_timeout.cpp b/src/mbgl/util/http_timeout.cpp
new file mode 100644
index 0000000000..ded0128ac9
--- /dev/null
+++ b/src/mbgl/util/http_timeout.cpp
@@ -0,0 +1,40 @@
+#include <mbgl/util/http_timeout.hpp>
+#include <mbgl/util/constants.hpp>
+
+namespace mbgl {
+namespace http {
+
+Duration errorRetryTimeout(Response::Error::Reason failedRequestReason, uint32_t failedRequests, optional<Timestamp> retryAfter) {
+
+ if (failedRequestReason == Response::Error::Reason::Server) {
+ // Retry after one second three times, then start exponential backoff.
+ return Seconds(failedRequests <= 3 ? 1 : 1u << std::min(failedRequests - 3, 31u));
+ } else if (failedRequestReason == Response::Error::Reason::Connection) {
+ // Immediate exponential backoff.
+ assert(failedRequests > 0);
+ return Seconds(1u << std::min(failedRequests - 1, 31u));
+ } else if (failedRequestReason == Response::Error::Reason::RateLimit) {
+ if (retryAfter) {
+ return *retryAfter - util::now();
+ } else {
+ //Default
+ return Seconds(util::DEFAULT_RATE_LIMIT_TIMEOUT);
+ }
+ } else {
+ // No error, or not an error that triggers retries.
+ return Duration::max();
+ }
+}
+
+Duration expirationTimeout(optional<Timestamp> expires, uint32_t expiredRequests) {
+ if (expiredRequests) {
+ return Seconds(1u << std::min(expiredRequests - 1, 31u));
+ } else if (expires) {
+ return std::max(Seconds::zero(), *expires - util::now());
+ } else {
+ return Duration::max();
+ }
+}
+
+} // namespace http
+} // namespace mbgl
diff --git a/src/mbgl/util/http_timeout.hpp b/src/mbgl/util/http_timeout.hpp
new file mode 100644
index 0000000000..b694794997
--- /dev/null
+++ b/src/mbgl/util/http_timeout.hpp
@@ -0,0 +1,15 @@
+#pragma once
+
+#include <mbgl/storage/response.hpp>
+#include <mbgl/util/optional.hpp>
+#include <mbgl/util/chrono.hpp>
+
+namespace mbgl {
+namespace http {
+
+Duration errorRetryTimeout(Response::Error::Reason failedRequestReason, uint32_t failedRequests, optional<Timestamp> retryAfter = {});
+
+Duration expirationTimeout(optional<Timestamp> expires, uint32_t expiredRequests);
+
+} // namespace http
+} // namespace mbgl