From 0519ebae651d8d7466d4392a2ddb718c19c5c650 Mon Sep 17 00:00:00 2001 From: Dmitry Mikushin Date: Sat, 11 Feb 2023 02:03:44 +0100 Subject: Repeat the http request on fail, do not crash with an exception. This is a better design, because Telegram end point sometimes may not respond --- src/Api.cpp | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/Api.cpp b/src/Api.cpp index 54854f8..dcb2b36 100644 --- a/src/Api.cpp +++ b/src/Api.cpp @@ -1,5 +1,8 @@ #include "tgbot/Api.h" +#include +#include + namespace TgBot { Api::Api(std::string token, const HttpClient& httpClient, const std::string& url) @@ -2496,20 +2499,25 @@ boost::property_tree::ptree Api::sendRequest(const std::string& method, const st url += "/"; url += method; - std::string serverResponse = _httpClient.makeRequest(url, args); - if (!serverResponse.compare(0, 6, "")) { - throw TgException("tgbot-cpp library have got html page instead of json response. Maybe you entered wrong bot token."); - } + while(1) + { + std::string serverResponse = _httpClient.makeRequest(url, args); + if (!serverResponse.compare(0, 6, "")) { + throw TgException("tgbot-cpp library have got html page instead of json response. Maybe you entered wrong bot token."); + } - boost::property_tree::ptree result = _tgTypeParser.parseJson(serverResponse); - try { - if (result.get("ok", false)) { - return result.get_child("result"); - } else { - throw TgException(result.get("description", "")); + boost::property_tree::ptree result = _tgTypeParser.parseJson(serverResponse); + try { + if (result.get("ok", false)) { + return result.get_child("result"); + } else { + std::this_thread::sleep_for(std::chrono::seconds(1)); + continue; + //throw TgException(result.get("description", "")); + } + } catch (boost::property_tree::ptree_error& e) { + throw TgException("tgbot-cpp library can't parse json response. " + std::string(e.what())); } - } catch (boost::property_tree::ptree_error& e) { - throw TgException("tgbot-cpp library can't parse json response. " + std::string(e.what())); } } } -- cgit v1.2.3 From 97b0eb447e36308cd6783add28de88e429627bfe Mon Sep 17 00:00:00 2001 From: Dmitry Mikushin Date: Sun, 12 Feb 2023 22:38:29 +0100 Subject: Parameterizing the number of retries and backoff duration for HttpClient.makeRequest --- include/tgbot/net/HttpClient.h | 12 ++++++++++++ src/Api.cpp | 15 +++++++++++---- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/include/tgbot/net/HttpClient.h b/include/tgbot/net/HttpClient.h index 024c8ad..90b93dd 100644 --- a/include/tgbot/net/HttpClient.h +++ b/include/tgbot/net/HttpClient.h @@ -28,6 +28,18 @@ public: virtual std::string makeRequest(const Url& url, const std::vector& args) const = 0; std::int32_t _timeout = 25; + + virtual int getRequestMaxRetries() const { + return requestMaxRetries; + } + + virtual int getRequestBackoff() const { + return requestBackoff; + } + +private: + int requestMaxRetries = 3; + int requestBackoff = 1; }; } diff --git a/src/Api.cpp b/src/Api.cpp index dcb2b36..b6dba9a 100644 --- a/src/Api.cpp +++ b/src/Api.cpp @@ -2499,7 +2499,9 @@ boost::property_tree::ptree Api::sendRequest(const std::string& method, const st url += "/"; url += method; - while(1) + int requestRetryBackoff = _httpClient.getRequestBackoff(); + int retries = 0; + while (1) { std::string serverResponse = _httpClient.makeRequest(url, args); if (!serverResponse.compare(0, 6, "")) { @@ -2511,9 +2513,14 @@ boost::property_tree::ptree Api::sendRequest(const std::string& method, const st if (result.get("ok", false)) { return result.get_child("result"); } else { - std::this_thread::sleep_for(std::chrono::seconds(1)); - continue; - //throw TgException(result.get("description", "")); + if (retries == _httpClient.getRequestMaxRetries()) { + throw TgException(result.get("description", "")); + } + else { + std::this_thread::sleep_for(std::chrono::seconds(requestRetryBackoff)); + retries++; + continue; + } } } catch (boost::property_tree::ptree_error& e) { throw TgException("tgbot-cpp library can't parse json response. " + std::string(e.what())); -- cgit v1.2.3 From 69e2faa1828eb9c73b592faa69a64ea6c98ec6cf Mon Sep 17 00:00:00 2001 From: Dmitry Mikushin Date: Sun, 12 Feb 2023 22:42:03 +0100 Subject: Adding briefs for the new functions --- include/tgbot/net/HttpClient.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/tgbot/net/HttpClient.h b/include/tgbot/net/HttpClient.h index 90b93dd..9b93328 100644 --- a/include/tgbot/net/HttpClient.h +++ b/include/tgbot/net/HttpClient.h @@ -29,10 +29,16 @@ public: std::int32_t _timeout = 25; + /** + * @brief Get the maximum number of makeRequest() retries before giving up and throwing an exception. + */ virtual int getRequestMaxRetries() const { return requestMaxRetries; } + /** + * @brief Get the makeRequest() backoff duration between retries, in seconds. + */ virtual int getRequestBackoff() const { return requestBackoff; } -- cgit v1.2.3 From 6da263a5cf24503b1c87a7777bc79a2aab9d553b Mon Sep 17 00:00:00 2001 From: Dmitry Mikushin Date: Thu, 9 Mar 2023 11:30:17 +0100 Subject: Correcting the retry-able try-catch block placement: it must be the topmost in the retry loop, enclosing everything --- src/Api.cpp | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/Api.cpp b/src/Api.cpp index b6dba9a..202fb73 100644 --- a/src/Api.cpp +++ b/src/Api.cpp @@ -2503,27 +2503,31 @@ boost::property_tree::ptree Api::sendRequest(const std::string& method, const st int retries = 0; while (1) { - std::string serverResponse = _httpClient.makeRequest(url, args); - if (!serverResponse.compare(0, 6, "")) { - throw TgException("tgbot-cpp library have got html page instead of json response. Maybe you entered wrong bot token."); - } - - boost::property_tree::ptree result = _tgTypeParser.parseJson(serverResponse); try { - if (result.get("ok", false)) { - return result.get_child("result"); - } else { - if (retries == _httpClient.getRequestMaxRetries()) { + std::string serverResponse = _httpClient.makeRequest(url, args); + if (!serverResponse.compare(0, 6, "")) { + throw TgException("tgbot-cpp library have got html page instead of json response. Maybe you entered wrong bot token."); + } + + boost::property_tree::ptree result = _tgTypeParser.parseJson(serverResponse); + try { + if (result.get("ok", false)) { + return result.get_child("result"); + } else { throw TgException(result.get("description", "")); } - else { - std::this_thread::sleep_for(std::chrono::seconds(requestRetryBackoff)); - retries++; - continue; - } + } catch (boost::property_tree::ptree_error& e) { + throw TgException("tgbot-cpp library can't parse json response. " + std::string(e.what())); + } + } catch (...) { + int max_retries = _httpClient.getRequestMaxRetries(); + if ((max_retries >= 0) && (retries == max_retries)) { + throw; + } else { + std::this_thread::sleep_for(std::chrono::seconds(requestRetryBackoff)); + retries++; + continue; } - } catch (boost::property_tree::ptree_error& e) { - throw TgException("tgbot-cpp library can't parse json response. " + std::string(e.what())); } } } -- cgit v1.2.3