Skip to content

Commit

Permalink
Actually check for unuplaoded changes in no_pending_local_changes()
Browse files Browse the repository at this point in the history
We can have local changesets stored which have already been uploaded and
acknoledged by the server, so checking all of the changesets is incorrect. We
need to instead only check changesets for versions after the current position
of the upload cursor.
  • Loading branch information
tgoyne committed Aug 9, 2024
1 parent 05805d7 commit 9252ccc
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* Fixed conflict resolution bug related to ArrayErase and Clear instructions, which could sometimes cause an "Invalid prior_size" exception to prevent synchronization ([#7893](https://github.com/realm/realm-core/issues/7893), since v14.8.0).
* Fixed bug which would prevent eventual consistency during conflict resolution. Affected clients would experience data divergence and potentially consistency errors as a result. ([PR #7955](https://github.com/realm/realm-core/pull/7955), since v14.8.0)
* Fixed issues loading the native Realm libraries on Linux ARMv7 systems when they linked against our bundled OpenSSL resulting in errors like `unexpected reloc type 0x03`. ([#7947](https://github.com/realm/realm-core/issues/7947), since v14.1.0)
* `Realm::convert()` would sometimes incorrectly throw an exception claiming that there were unuploaded local changes when the source Realm is a synchronized Realm ([#7966](https://github.com/realm/realm-core/issues/7966), since v10.7.0).

### Breaking changes
* None.
Expand Down
7 changes: 6 additions & 1 deletion src/realm/sync/noinst/client_history_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1064,7 +1064,12 @@ void ClientHistory::trim_sync_history()
bool ClientHistory::no_pending_local_changes(version_type version) const
{
ensure_updated(version);
for (size_t i = 0; i < sync_history_size(); i++) {
size_t base_version = 0;
auto upload_client_version =
version_type(m_arrays->root.get_as_ref_or_tagged(s_progress_upload_client_version_iip).get_as_int());
if (upload_client_version > m_sync_history_base_version)
base_version = size_t(upload_client_version - m_sync_history_base_version);
for (size_t i = base_version; i < sync_history_size(); i++) {
if (m_arrays->origin_file_idents.get(i) == 0) {
std::size_t pos = 0;
BinaryData chunk = m_arrays->changesets.get_at(i, pos);
Expand Down
37 changes: 37 additions & 0 deletions test/object-store/realm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1647,6 +1647,43 @@ TEST_CASE("SharedRealm: convert", "[sync][pbs][convert]") {
// Check that the data also exists in the new realm
REQUIRE(local_realm2->read_group().get_table("class_object")->size() == 1);
}

SECTION("synced realm must be fully uploaded") {
auto realm = Realm::get_shared_realm(sync_config1);
realm->sync_session()->pause();
realm->begin_transaction();
realm->read_group().get_table("class_object")->create_object_with_primary_key(0);
realm->commit_transaction();

SyncTestFile sync_config2(tsm, "default");
sync_config2.schema = schema;
REQUIRE_EXCEPTION(realm->convert(sync_config2), IllegalOperation,
"All client changes must be integrated in server before writing copy");

realm->sync_session()->resume();
wait_for_upload(*realm);
REQUIRE_NOTHROW(realm->convert(sync_config2));
}

SECTION("can convert synced realm from within upload complete callback") {
auto realm = Realm::get_shared_realm(sync_config1);
realm->sync_session()->pause();
realm->begin_transaction();
realm->read_group().get_table("class_object")->create_object_with_primary_key(0);
realm->commit_transaction();

SyncTestFile sync_config2(tsm, "default");
sync_config2.schema = schema;
auto pf = util::make_promise_future();
realm->sync_session()->wait_for_upload_completion([&](Status) {
sync_config1.scheduler = util::Scheduler::make_dummy();
auto realm = Realm::get_shared_realm(sync_config1);
REQUIRE_NOTHROW(realm->convert(sync_config2));
pf.promise.emplace_value();
});
realm->sync_session()->resume();
pf.future.get();
}
}

TEST_CASE("SharedRealm: convert - embedded objects", "[sync][pbs][convert][embedded objects]") {
Expand Down

0 comments on commit 9252ccc

Please sign in to comment.