-
Notifications
You must be signed in to change notification settings - Fork 167
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
Fix crash when opening FLX realm after client reset failure #6671
Merged
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
cf58a7e
Fix crash when opening FLX realm after client reset failure
danieltabacaru 3bce4a0
Update changelog
danieltabacaru dfc3b65
Don't superceed pending subscriptions in case of a client reset failure
danieltabacaru 31e4a81
Add test
danieltabacaru 161b76b
Merge branch 'master' into dt/fix_client_reset_crash
danieltabacaru 538fdab
Changes after code review
danieltabacaru File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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 |
---|---|---|
|
@@ -40,6 +40,7 @@ | |
#include "realm/sync/client_base.hpp" | ||
#include "realm/sync/config.hpp" | ||
#include "realm/sync/noinst/client_history_impl.hpp" | ||
#include <realm/sync/noinst/client_reset_operation.hpp> | ||
#include "realm/sync/noinst/pending_bootstrap_store.hpp" | ||
#include "realm/sync/noinst/server/access_token.hpp" | ||
#include "realm/sync/protocol.hpp" | ||
|
@@ -282,6 +283,11 @@ TEST_CASE("flx: client reset", "[sync][flx][app][client reset]") { | |
{"list_of_ints_field", PropertyType::Int | PropertyType::Array}, | ||
{"sum_of_list_field", PropertyType::Int}, | ||
}}, | ||
{"TopLevel2", | ||
{ | ||
{"_id", PropertyType::ObjectId, Property::IsPrimary{true}}, | ||
{"queryable_str_field", PropertyType::String | PropertyType::Nullable}, | ||
}}, | ||
}; | ||
|
||
// some of these tests make additive schema changes which is only allowed in dev mode | ||
|
@@ -432,6 +438,58 @@ TEST_CASE("flx: client reset", "[sync][flx][app][client reset]") { | |
->run(); | ||
} | ||
|
||
SECTION("Recover: subscription and offline writes after client reset failure") { | ||
config_local.sync_config->client_resync_mode = ClientResyncMode::Recover; | ||
auto&& [error_future, error_handler] = make_error_handler(); | ||
config_local.sync_config->error_handler = error_handler; | ||
|
||
std::string fresh_path = realm::_impl::ClientResetOperation::get_fresh_path_for(config_local.path); | ||
// create a non-empty directory that we'll fail to delete | ||
util::make_dir(fresh_path); | ||
util::File(util::File::resolve("file", fresh_path), util::File::mode_Write); | ||
|
||
auto test_reset = reset_utils::make_baas_flx_client_reset(config_local, config_remote, harness.session()); | ||
test_reset | ||
->make_local_changes([&](SharedRealm local_realm) { | ||
auto mut_sub = local_realm->get_latest_subscription_set().make_mutable_copy(); | ||
auto table = local_realm->read_group().get_table("class_TopLevel2"); | ||
mut_sub.insert_or_assign(Query(table)); | ||
mut_sub.commit(); | ||
|
||
CppContext c(local_realm); | ||
local_realm->begin_transaction(); | ||
Object::create(c, local_realm, "TopLevel2", | ||
std::any(AnyDict{{"_id"s, ObjectId::gen()}, {"queryable_str_field"s, "foo"s}})); | ||
local_realm->commit_transaction(); | ||
}) | ||
->on_post_reset([](SharedRealm local_realm) { | ||
// Verify offline subscription was not removed. | ||
auto subs = local_realm->get_latest_subscription_set(); | ||
auto table = local_realm->read_group().get_table("class_TopLevel2"); | ||
REQUIRE(subs.find(Query(table))); | ||
}) | ||
->run(); | ||
|
||
// Remove the folder preventing the completion of a client reset. | ||
util::try_remove_dir_recursive(fresh_path); | ||
|
||
auto config_copy = config_local; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like this is working, but I think you could strengthen this test by using |
||
config_local.sync_config->error_handler = nullptr; | ||
auto&& [reset_future, reset_handler] = make_client_reset_handler(); | ||
config_copy.sync_config->notify_after_client_reset = reset_handler; | ||
|
||
// Attempt to open the realm again. | ||
// This time the client reset succeeds and the offline subscription and writes are recovered. | ||
auto realm = Realm::get_shared_realm(config_copy); | ||
ClientResyncMode mode = reset_future.get(); | ||
REQUIRE(mode == ClientResyncMode::Recover); | ||
|
||
auto table = realm->read_group().get_table("class_TopLevel2"); | ||
auto str_col = table->get_column_key("queryable_str_field"); | ||
REQUIRE(table->size() == 1); | ||
REQUIRE(table->get_object(0).get<String>(str_col) == "foo"); | ||
} | ||
|
||
SECTION("Recover: offline writes and subscriptions (multiple subscriptions)") { | ||
config_local.sync_config->client_resync_mode = ClientResyncMode::Recover; | ||
auto&& [reset_future, reset_handler] = make_client_reset_handler(); | ||
|
@@ -811,6 +869,36 @@ TEST_CASE("flx: client reset", "[sync][flx][app][client reset]") { | |
}) | ||
->run(); | ||
} | ||
|
||
SECTION("DiscardLocal: open realm after client reset failure") { | ||
config_local.sync_config->client_resync_mode = ClientResyncMode::DiscardLocal; | ||
auto&& [error_future, error_handler] = make_error_handler(); | ||
config_local.sync_config->error_handler = error_handler; | ||
|
||
std::string fresh_path = realm::_impl::ClientResetOperation::get_fresh_path_for(config_local.path); | ||
// create a non-empty directory that we'll fail to delete | ||
util::make_dir(fresh_path); | ||
util::File(util::File::resolve("file", fresh_path), util::File::mode_Write); | ||
|
||
auto test_reset = reset_utils::make_baas_flx_client_reset(config_local, config_remote, harness.session()); | ||
test_reset->run(); | ||
|
||
// Client reset fails due to sync client not being able to create the fresh realm. | ||
auto sync_error = wait_for_future(std::move(error_future)).get(); | ||
CHECK(sync_error.get_system_error() == sync::make_error_code(sync::ClientError::auto_client_reset_failure)); | ||
|
||
// Open the realm again. This should not crash. | ||
{ | ||
auto config_copy = config_local; | ||
auto&& [err_future, err_handler] = make_error_handler(); | ||
config_local.sync_config->error_handler = err_handler; | ||
|
||
auto realm_post_reset = Realm::get_shared_realm(config_copy); | ||
auto sync_error = wait_for_future(std::move(err_future)).get(); | ||
CHECK(sync_error.get_system_error() == | ||
sync::make_error_code(sync::ClientError::auto_client_reset_failure)); | ||
} | ||
} | ||
} | ||
|
||
TEST_CASE("flx: creating an object on a class with no subscription throws", "[sync][flx][app]") { | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
💯