-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: more helpful error messages for streaming connection failures (#419
) This commit pulls the stringification logic of SSE errors into the SSE package itself, and refactors the enum into a richer sum type using `std::variant`. It also introduces a more helpful log message when SDK key is invalid.
- Loading branch information
1 parent
5cb99ae
commit 6bd21ba
Showing
7 changed files
with
117 additions
and
61 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
45 changes: 39 additions & 6 deletions
45
libs/server-sent-events/include/launchdarkly/sse/error.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,44 @@ | ||
#pragma once | ||
#include <chrono> | ||
#include <optional> | ||
#include <ostream> | ||
#include <variant> | ||
|
||
#include <boost/beast/http/status.hpp> | ||
|
||
namespace launchdarkly::sse { | ||
namespace errors { | ||
|
||
struct NoContent {}; | ||
std::ostream& operator<<(std::ostream& out, NoContent const&); | ||
|
||
struct InvalidRedirectLocation { | ||
std::string location; | ||
}; | ||
std::ostream& operator<<(std::ostream& out, InvalidRedirectLocation const&); | ||
|
||
struct NotRedirectable {}; | ||
std::ostream& operator<<(std::ostream& out, NotRedirectable const&); | ||
|
||
enum class Error { | ||
NoContent = 1, | ||
InvalidRedirectLocation = 2, | ||
UnrecoverableClientError = 3, | ||
ReadTimeout = 4, | ||
struct ReadTimeout { | ||
std::optional<std::chrono::milliseconds> timeout; | ||
}; | ||
} | ||
std::ostream& operator<<(std::ostream& out, ReadTimeout const&); | ||
|
||
struct UnrecoverableClientError { | ||
boost::beast::http::status status; | ||
}; | ||
std::ostream& operator<<(std::ostream& out, UnrecoverableClientError const&); | ||
|
||
} // namespace errors | ||
|
||
using Error = std::variant<errors::NoContent, | ||
errors::InvalidRedirectLocation, | ||
errors::NotRedirectable, | ||
errors::ReadTimeout, | ||
errors::UnrecoverableClientError>; | ||
|
||
std::ostream& operator<<(std::ostream& out, Error const& error); | ||
|
||
std::string ErrorToString(Error const& error); | ||
} // namespace launchdarkly::sse |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
#include <launchdarkly/sse/error.hpp> | ||
|
||
#include <sstream> | ||
|
||
namespace launchdarkly::sse { | ||
namespace errors { | ||
|
||
std::ostream& operator<<(std::ostream& out, NoContent const&) { | ||
out << "received HTTP error 204 (no content) - giving up " | ||
"permanently"; | ||
return out; | ||
} | ||
|
||
std::ostream& operator<<(std::ostream& out, | ||
InvalidRedirectLocation const& invalid) { | ||
out << "received invalid redirect from server, cannot follow (" | ||
<< invalid.location << ") - giving up permanently"; | ||
return out; | ||
} | ||
|
||
std::ostream& operator<<(std::ostream& out, NotRedirectable const&) { | ||
out << "received malformed redirect from server, cannot follow - giving up " | ||
"permanently"; | ||
return out; | ||
} | ||
|
||
std::ostream& operator<<(std::ostream& out, ReadTimeout const& err) { | ||
out << "timed out reading response body (exceeded " << err.timeout->count() | ||
<< "ms) - will retry"; | ||
return out; | ||
} | ||
|
||
std::ostream& operator<<(std::ostream& out, | ||
UnrecoverableClientError const& err) { | ||
std::string explanation; | ||
if (err.status == boost::beast::http::status::unauthorized || | ||
err.status == boost::beast::http::status::forbidden) { | ||
explanation = " (invalid auth key)"; | ||
} | ||
out << "received HTTP error " << static_cast<int>(err.status) << explanation | ||
<< " for streaming connection - giving up " | ||
"permanently"; | ||
return out; | ||
} | ||
} // namespace errors | ||
|
||
std::ostream& operator<<(std::ostream& out, Error const& error) { | ||
std::visit( | ||
[&](auto&& arg) { | ||
using T = std::decay_t<decltype(arg)>; | ||
out << arg; | ||
}, | ||
error); | ||
return out; | ||
} | ||
|
||
std::string ErrorToString(Error const& error) { | ||
std::stringstream ss; | ||
ss << error; | ||
return ss.str(); | ||
} | ||
|
||
} // namespace launchdarkly::sse |