-
Notifications
You must be signed in to change notification settings - Fork 169
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
RCORE-2060 Enabling 'cancel_waits_on_nonfatal_error' does not cancel waits during location update while offline #7528
RCORE-2060 Enabling 'cancel_waits_on_nonfatal_error' does not cancel waits during location update while offline #7528
Conversation
…ring location update
…cel-waits-on-nonfatal-error
Pull Request Test Coverage Report for Build michael.wilkersonbarker_1057Details
💛 - Coveralls |
Hi @tgoyne or @dianaafanador3 - would either of you mind trying these changes out with the Swift |
test/object-store/realm.cpp
Outdated
location_refresh_called = true; | ||
if (mode == location_fails) { | ||
// Fake "offline/request timed out" custom error response | ||
return app::Response{0, 28, {}, "Operation timed out"}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does the 28 have some special significance?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not really - it just corresponded with CURLE_OPERATION_TIMEDOUT (28)
, since there really isn't a default error returned when the operation times out and is more transport implementation specific.
https://curl.se/libcurl/c/libcurl-errors.html#:~:text=CURLE_OPERATION_TIMEDOUT
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a define for the value to try to explain why the value is being used.
@michael-wb Is is a guarantee that AutoOpen sets SyncConfig::cancel_waits_on_nonfatal_error to true? |
Yes - here is where it is being set: https://github.com/realm/realm-swift/blob/master/RealmSwift/SwiftUI.swift#L1533-L1540 |
…cel-waits-on-nonfatal-error
test/object-store/realm.cpp
Outdated
|
||
SyncTestFile config(oas, "realm"); | ||
auto user = config.sync_config->user; | ||
config.sync_config->cancel_waits_on_nonfatal_error = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we add a test (maybe already have one?) when this is false?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it's needed...
When this is false, the session will continue with retrying to connect to the server, so the test case expectations will be different. In addition, all the other aynsc open tests (as well as many others), validate the sync client operation with this flag set to false (the default).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, what I meant is to test that behavior and expectations too (in a separate test not as a section). But I think you added a test in the previous PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the tests added in the previous PR should test the normal cases; although I could add an additional test specifically for async open if you think that is necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚢 🇮🇹
test/object-store/realm.cpp
Outdated
TestMode mode = GENERATE(location_fails, token_fails, token_not_authorized); | ||
|
||
SECTION(util::format("access token expired when realm is opened - mode: %1", txt_test_mode(mode))) { | ||
logger->trace(">>> access token expired when realm is opened - mode: %1", txt_test_mode(mode)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: if this is mainly for CI, I don't think we run the tests with trace logs (could use debug)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These were originally in for debugging the tests, but I ended up removing them from the test.
test/object-store/realm.cpp
Outdated
REQUIRE_FALSE(error.is_fatal); | ||
return; | ||
} | ||
if (error.status.code() == ErrorCodes::AuthError) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looking at the websocket replies, these are the only two errors allowed. you could just:
REQUIRE(error.status.code() == ErrorCodes::AuthError);
REQUIRE(error.is_fatal);
test/object-store/realm.cpp
Outdated
|
||
TestMode mode = GENERATE(location_fails, token_fails, token_not_authorized); | ||
|
||
SECTION(util::format("access token expired when realm is opened - mode: %1", txt_test_mode(mode))) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Catch has DYNAMIC_SECTION for this: DYNAMIC_SECTION("access token expired when realm is opened - mode: " << txt_test_mode(mode))
.
This pattern of doing configuration in the SECTION and then the shared test afterwards has the problem that it results in catch not being able to tell us which section failed, and relying on logging for that is awkward. I think the intended way to do this with Catch would be using GENERATE on a second enum and switching on that instead of using sections. CAPTURE(mode)
can be used to make it print the generated mode on failure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good to know 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @tgoyne - I updated the tests to use the DYNAMIC_SECTION
so the individual sections would show up in the test results.
So I tested this with the template and we are no longer getting the connection when using AutoOpen, but I do get a lot of connection errors when recovering the connection. The message of the error is not very detailed. |
Thank you @dianaafanador3 - do you have a log file (maybe share via slack) and how is the connection recovered? using |
…cel-waits-on-nonfatal-error
…cel-waits-on-nonfatal-error
…cel-waits-on-nonfatal-error
…cel-waits-on-nonfatal-error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Errors are not longer showing during the manual testing, and offline data is synced when the connection is recovered.
…cel-waits-on-nonfatal-error
@danieltabacaru / @jbreams - This has been updated to the latest |
src/realm/object-store/sync/app.cpp
Outdated
@@ -1284,14 +1285,17 @@ void App::refresh_access_token(const std::shared_ptr<User>& user, bool update_lo | |||
return; | |||
} | |||
|
|||
log_debug("App: refresh_access_token: email: %1 %2", user->user_profile().email(), | |||
update_location ? "(updating location)" : ""); | |||
log_debug("App: refresh_access_token: user-id: %1%2", user->user_id(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: user_id
// Close the app instance (or tear down the TestAppSession) | ||
void close(bool tear_down = false); | ||
// Re-open the app instance using app_config | ||
void reopen(bool log_in = false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this needed? 🤔 Can't you create a new TestAppSession if needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is so I can shut down and restart the app and retain the same metadata realm and logged in user in order to simulate the "restart client app with cached user" issue where the location info hasn't been queried yet when the sync session is started.
If I create a new TestAppSession, it will create a new directory and a new logged in user (which will request the location info in the process).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
got it. it may be worth being able to create a TestAppSession that retains the same metadata realm (i.e, by passing the directory and check if the realm exists, otherwise start from fresh).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer to have TestAppSession remain a strictly scoped type and have a way to reuse a metadata directory between instances, but it's also not a big deal and not worth spending much time on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can update this in a future PR.
src/realm/exceptions.cpp
Outdated
{ | ||
try { | ||
if (exc_ptr) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't appear to be used anywhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was previously using this to get the exception thrown in the Async open start callback, but not anymore. Removed this unused code.
test/object-store/realm.cpp
Outdated
@@ -1348,6 +1495,111 @@ TEST_CASE("Get Realm using Async Open", "[sync][pbs][async open]") { | |||
} | |||
} | |||
|
|||
#if REALM_ENABLE_AUTH_TESTS | |||
#if REALM_APP_SERVICES |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
REALM_ENABLE_AUTH_TESTS implies REALM_APP_SERVICES so they don't both need to be checked.
* Prepare release * [bindgen] expose both SyncUser and app::User (#7634) * RCORE-2060 Enabling 'cancel_waits_on_nonfatal_error' does not cancel waits during location update while offline (#7528) * added tests using cancel_waits_on_nonfatal_error and fix operation during location update * Updated changelog and updated comments/debug statements * fix swift build and test and tsan errors * Added test to replicate swift autoopen feature * Fixed swift build issue * removed an unused function * Updates from review --------- Co-authored-by: Kenneth Geisshirt <[email protected]> Co-authored-by: Michael Wilkerson-Barker <[email protected]>
…waits during location update while offline (#7528) * added tests using cancel_waits_on_nonfatal_error and fix operation during location update * Updated changelog and updated comments/debug statements * fix swift build and test and tsan errors * Added test to replicate swift autoopen feature * Fixed swift build issue * removed an unused function * Updates from review
What, How & Why?
After the location update fixes in #7469, the operation of
@AutoOpen
in the Swift SDK was still an issue if the Realm needed to update the location and was currently offline. In order for@AutoOpen
to work, the sync session needs to cancel any waiters with an error if the websocket connection to the server is not successful, which is done by setting theSyncConfig::cancel_waits_on_nonfatal_error
flag totrue
.This PR fixes this operation and adds tests for the
SyncConfig::cancel_waits_on_nonfatal_error
setting since these did not currently exist.Fixes #7527
☑️ ToDos
[ ] C-API, if public C++ API changed[ ]bindgen/spec.yml
, if public C++ API changed