2727#include " logger.h"
2828
2929#include < cassert> // assert
30+ #include < chrono> // std::chrono::seconds
31+ #include < cstdint> // std::uint8_t
3032#include < filesystem> // std::filesystem
3133#include < functional> // std::function, std::ref
3234#include < iostream> // std::cerr
3638#include < stdexcept> // std::runtime_error
3739#include < string> // std::string
3840#include < string_view> // std::string_view
41+ #include < thread> // std::this_thread::sleep_for
3942#include < utility> // std::pair, std::piecewise_construct, std::forward_as_tuple
4043
4144namespace sourcemeta ::jsonschema {
4245
46+ static constexpr std::uint8_t HTTP_MAXIMUM_RETRIES{3 };
47+
4348static inline auto fallback_resolver (const sourcemeta::core::Options &options,
4449 std::string_view identifier)
4550 -> std::optional<sourcemeta::core::JSON> {
@@ -56,9 +61,24 @@ static inline auto fallback_resolver(const sourcemeta::core::Options &options,
5661 return std::nullopt ;
5762 }
5863
59- LOG_VERBOSE (options) << " Resolving over HTTP: " << identifier << " \n " ;
60- const cpr::Response response{
61- cpr::Get (cpr::Url{identifier}, cpr::Redirect{true })};
64+ cpr::Response response;
65+ for (std::uint8_t attempt{1 }; attempt <= HTTP_MAXIMUM_RETRIES; ++attempt) {
66+ LOG_VERBOSE (options) << " Resolving over HTTP (attempt "
67+ << static_cast <int >(attempt) << " /"
68+ << static_cast <int >(HTTP_MAXIMUM_RETRIES)
69+ << " ): " << identifier << " \n " ;
70+ response = cpr::Get (cpr::Url{identifier}, cpr::Redirect{true });
71+
72+ if (response.status_code == 200 ) {
73+ break ;
74+ }
75+
76+ if (attempt < HTTP_MAXIMUM_RETRIES) {
77+ LOG_VERBOSE (options) << " Request failed with HTTP "
78+ << response.status_code << " , retrying...\n " ;
79+ std::this_thread::sleep_for (std::chrono::seconds (1 ));
80+ }
81+ }
6282
6383 if (response.status_code != 200 ) {
6484 std::ostringstream error;
0 commit comments