Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle websocket errors entirely within sync client #6859

Merged
merged 16 commits into from
Aug 8, 2023

Conversation

jbreams
Copy link
Contributor

@jbreams jbreams commented Aug 3, 2023

What, How & Why?

This makes the WebSocketError type just a normal enum that SocketProvider implementations can pass back to the sync client without having to use a special kind of error wrapper. Then, it makes it so all the websocket error handling happens inside of the sync client itself. If a specific websocket error requires a specific action out in object-store, this is handled by an error action rather than by exposing the implementation details of networking to object-store. Finally, this de-duplicates the try_again and is_fatal flag so that there's only an is_fatal flag that is a TaggedBool.

☑️ ToDos

  • 📝 Changelog update
  • 🚦 Tests (or not relevant)
  • C-API, if public C++ API changed.

@jbreams jbreams marked this pull request as ready for review August 4, 2023 19:07
@jbreams jbreams marked this pull request as draft August 4, 2023 22:24
@jbreams jbreams marked this pull request as ready for review August 5, 2023 17:48
SessionErrorInfo error_info{std::move(status), try_again};
involuntary_disconnect(std::move(error_info),
ConnectionTerminationReason::websocket_protocol_violation); // Throws
close_due_to_client_side_error({ErrorCodes::SyncProtocolInvariantFailed, msg}, IsFatal{false},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we try to get rid off of calling involuntary_disconnect directly and call close_due_to_... methods instead? I see you fixed it here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know? The difference between them right now is that close_due_to_ constructs a SessionErrorInfo for you. I'd almost go for getting rid of close_due_to_ methods in favor of involuntary_disconnect instead? But I don't feel very strongly either way.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. It could be involuntary_disconnect instead, but I don't really like having both.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, can I do that in a separate PR or do you need to see it done in this one?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not really now. It would be nice at some point.

@@ -1924,7 +1934,7 @@ void Session::send_ident_message()
m_client_file_ident.ident, m_client_file_ident.salt, m_progress.download.server_version,
m_progress.download.last_integrated_client_version, m_progress.latest_server_version.version,
m_progress.latest_server_version.salt, active_query_set.version(), active_query_body.size(),
active_query_body); // Throws
active_query_body); // T
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// Throws

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

@@ -258,22 +262,24 @@ struct ProtocolErrorInfo {
ClientReset,
ClientResetNoRecovery,
MigrateToFLX,
RevertToPBS
RevertToPBS,
RefreshUser,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the server send these two new actions? Or is it something we set internally? If it's the latter, maybe consider adding a comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now it's something we set internally, but the server could send it eventually.

Copy link
Collaborator

@danieltabacaru danieltabacaru left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Contributor

@michael-wb michael-wb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM - Thanks for making these changes.

Comment on lines +710 to +721
case sync::ProtocolErrorInfo::Action::RefreshUser:
if (auto u = user()) {
u->refresh_custom_data(false, handle_refresh(shared_from_this(), false));
return;
}
break;
case sync::ProtocolErrorInfo::Action::RefreshLocation:
if (auto u = user()) {
u->refresh_custom_data(true, handle_refresh(shared_from_this(), true));
return;
}
break;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice - so much cleaner

@@ -78,15 +78,13 @@ class DefaultWebSocketImpl final : public DefaultWebSocket, public Config {
{
m_logger.error("Reading failed: %1", ec.message()); // Throws
constexpr bool was_clean = false;
websocket_error_and_close_handler(
was_clean, Status{make_error_code(WebSocketError::websocket_read_error), ec.message()});
websocket_error_and_close_handler(was_clean, WebSocketError::websocket_read_error, ec.message());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So much cleaner

{
return "realm::sync::websocket::WebSocketError";
if (str == nullptr) {
os << "WebSocket: Unkhown Error (" << static_cast<std::underlying_type_t<WebSocketError>>(code) << ")";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unknown

@@ -431,7 +431,8 @@ TEST_CASE("sync: error handling", "[sync][session]") {
}

sync::SessionErrorInfo initial_error{
Status{std::error_code{code, realm::sync::protocol_error_category()}, "Something bad happened"}, true};
Status{std::error_code{code, realm::sync::protocol_error_category()}, "Something bad happened"},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will be nice once we're finally done with these...

Copy link
Member

@fealebenpae fealebenpae left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for simplifying the interface!

@jbreams jbreams merged commit a80ab11 into feature/sync_error_unification Aug 8, 2023
2 checks passed
@jbreams jbreams deleted the jbr/websocket_error branch August 8, 2023 19:52
jbreams added a commit that referenced this pull request Aug 11, 2023
* Add new ErrorCodes for sync error unification (#6829)

* Make SyncError/SessionErrorInfo Status-aware (#6824)

* Replace ClientError error_code with ErrorCodes/Status (#6846)

* Handle websocket errors entirely within sync client (#6859)

* Unify remaining std::error_codes into Status/ErrorCodes in sync client (#6869)

* fix changelog merge with master
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 21, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants