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

RCORE-2174 Bootstrap store is not being reset if initial subscription bootstrap is interrupted by role change #7831

Merged
merged 10 commits into from
Jul 1, 2024
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
* Fixed removing backlinks from the wrong objects if the link came from a nested list, nested dictionary, top-level dictionary, or list of mixed, and the source table had more than 256 objects. This could manifest as `array_backlink.cpp:112: Assertion failed: int64_t(value >> 1) == key.value` when removing an object. ([#7594](https://github.com/realm/realm-core/issues/7594), since v11 for dictionaries)
* Fixed the collapse/rejoin of clusters which contained nested collections with links. This could manifest as `array.cpp:319: Array::move() Assertion failed: begin <= end [2, 1]` when removing an object. ([#7839](https://github.com/realm/realm-core/issues/7839), since the introduction of nested collections in v14.0.0-beta.0)
* wait_for_upload_completion() was inconsistent in how it handled commits which did not produce any changesets to upload. Previously it would sometimes complete immediately if all commits waiting to be uploaded were empty, and at other times it would wait for a server roundtrip. It will now always complete immediately. ([PR #7796](https://github.com/realm/realm-core/pull/7796)).
* If a sync session is interrupted by a disconnect or restart while downloading a bootstrap, stale data from the previous bootstrap may be included when the session reconnects and downloads the bootstrap. This can lead to objects stored in the database that do not match the actual state of the server and potentially leading to compensating writes. ([#7827](https://github.com/realm/realm-core/issues/7827), since v12.0.0)

### Breaking changes
* None.
Expand Down
4 changes: 1 addition & 3 deletions src/realm/sync/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -836,7 +836,7 @@ bool SessionImpl::process_flx_bootstrap_message(const SyncProgress& progress, Do
}

try {
process_pending_flx_bootstrap();
process_pending_flx_bootstrap(); // throws
}
catch (const IntegrationException& e) {
on_integration_failure(e);
Expand All @@ -855,8 +855,6 @@ void SessionImpl::process_pending_flx_bootstrap()
if (!m_is_flx_sync_session || m_state != State::Active) {
return;
}
// Should never be called if session is not active
REALM_ASSERT_EX(m_state == SessionImpl::Active, m_state);
Copy link
Collaborator

Choose a reason for hiding this comment

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

this assertion didn't really make sense

auto bootstrap_store = m_wrapper.get_flx_pending_bootstrap_store();
if (!bootstrap_store->has_pending()) {
return;
Expand Down
12 changes: 11 additions & 1 deletion src/realm/sync/noinst/client_impl_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1527,6 +1527,16 @@ void Session::cancel_resumption_delay()
if (unbind_process_complete())
initiate_rebind(); // Throws

try {
process_pending_flx_bootstrap(); // throws
}
catch (const IntegrationException& error) {
on_integration_failure(error);
Copy link
Contributor

Choose a reason for hiding this comment

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

what happens if we have an integration failure here? I guess the client will just continue to resume the session but without applying the bootstrap?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes - it's the same if there is an integration failure during activate()

}
catch (...) {
on_integration_failure(IntegrationException(exception_to_status()));
}

m_conn.one_more_active_unsuspended_session(); // Throws
if (m_try_again_activation_timer) {
m_try_again_activation_timer.reset();
Expand Down Expand Up @@ -1717,7 +1727,7 @@ void Session::activate()
m_conn.one_more_active_unsuspended_session(); // Throws

try {
process_pending_flx_bootstrap();
process_pending_flx_bootstrap(); // throws
}
catch (const IntegrationException& error) {
on_integration_failure(error);
Expand Down
8 changes: 4 additions & 4 deletions test/object-store/sync/flx_role_change.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -775,9 +775,8 @@ TEST_CASE("flx: role changes during bootstrap complete successfully", "[sync][fl
}
SECTION("Role change during subscription bootstrap") {
auto realm_1 = Realm::get_shared_realm(config);
/// TODO: update to:
/// bool initial_subscription = GENERATE(false, true);
bool initial_subscription = true;
bool initial_subscription = GENERATE(false, true);

if (initial_subscription) {
auto table = realm_1->read_group().get_table("class_Person");
auto role_col = table->get_column_key("role");
Expand All @@ -799,9 +798,10 @@ TEST_CASE("flx: role changes during bootstrap complete successfully", "[sync][fl
// The test will update the rule to change access from all records to only the employee
// records while a new subscription for all Person entries is being bootstrapped.
update_role(default_rule, {{"role", "employee"}});

// Set up a new bootstrap while offline
realm_1->sync_session()->shutdown_and_wait();
{
// Set up a new bootstrap while offline
auto table = realm_1->read_group().get_table("class_Person");
auto new_subs = realm_1->get_latest_subscription_set().make_mutable_copy();
new_subs.clear();
Expand Down
Loading