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-2030 Add full support for automatic client reset for collections in mixed #7683

Merged

Conversation

danieltabacaru
Copy link
Collaborator

@danieltabacaru danieltabacaru commented May 8, 2024

What, How & Why?

The recovery of local instructions operating on nested collections follows closely the recovery of operations on embedded objects (you can think of a nested dictionary or list as an embedded object).

Notably:

  • list operations (including accessing an element in an intermediate list) are only applied if they involve elements inserted during the recovery, otherwise the entire list is copied verbatim
  • clearing a collection sets the collection type too (even if it was changed remotely), essentially allowing to recover subsequent operations on that collection

Additionally, I fixed a crash when recovering AddInteger instructions on a non-integer value (changed remotely).

Fixes #7490.

☑️ ToDos

  • 📝 Changelog update
  • 🚦 Tests (or not relevant)
  • [ ] C-API, if public C++ API changed
  • [ ] bindgen/spec.yml, if public C++ API changed

@danieltabacaru danieltabacaru marked this pull request as ready for review May 8, 2024 16:20
Copy link

coveralls-official bot commented May 8, 2024

Pull Request Test Coverage Report for Build daniel.tabacaru_829

Details

  • 1553 of 1601 (97.0%) changed or added relevant lines in 6 files are covered.
  • 71 unchanged lines in 17 files lost coverage.
  • Overall coverage increased (+0.06%) to 90.832%

Changes Missing Coverage Covered Lines Changed/Added Lines %
src/realm/sync/changeset.cpp 0 1 0.0%
src/realm/sync/noinst/client_reset_recovery.cpp 117 121 96.69%
src/realm/sync/instruction_applier.cpp 62 105 59.05%
Files with Coverage Reduction New Missed Lines %
src/realm/array_mixed.cpp 1 91.91%
src/realm/object_converter.cpp 1 96.58%
src/realm/sync/changeset.cpp 1 39.71%
src/realm/sync/noinst/client_reset_recovery.cpp 1 91.16%
src/realm/util/file.cpp 1 78.73%
src/realm/uuid.cpp 1 98.48%
test/fuzz_tester.hpp 1 57.73%
test/test_query2.cpp 1 98.73%
test/test_util_network.cpp 1 95.56%
src/realm/cluster.cpp 2 75.6%
Totals Coverage Status
Change from base Build 2300: 0.06%
Covered Lines: 214570
Relevant Lines: 236228

💛 - Coveralls

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.

Still reviewing, but here's my first couple of minor comments

auto size_src = n_src_list->size();
auto size_dst = n_dst_list->size();
if (size_src != size_dst)
REALM_ASSERT(src_dictionary.contains(key) && dst_dictionary.contains(key));
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we just return false here instead of an assert?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

it's sort of a problem if the key (and the indexes in check_matching_list) is not in the dictionary. the caller ensures that (haven't really changed that). I added these to mostly catch unexpected behavior during development (i could turn it into debug asserts if it makes more sense).

Copy link
Contributor

Choose a reason for hiding this comment

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

Agreed.

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.

Still reviewing, but here's my first couple of minor comments

@@ -626,52 +626,68 @@ void RecoverLocalChangesetsHandler::copy_lists_with_unrecoverable_changes()
bool RecoverLocalChangesetsHandler::resolve_path(ListPath& path, Obj remote_obj, Obj local_obj,
Copy link
Contributor

Choose a reason for hiding this comment

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

This method is one of the trickier changes in this PR, could you take a look at the coverage report and try to test some more of the uncovered corner cases?

Copy link
Contributor

Choose a reason for hiding this comment

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

agreed.

Copy link
Contributor

@ironage ironage left a comment

Choose a reason for hiding this comment

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

A couple of minor suggestions but otherwise LGTM!

Copy link
Contributor

@jbreams jbreams left a comment

Choose a reason for hiding this comment

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

Looking good so far.

auto size_src = n_src_list->size();
auto size_dst = n_dst_list->size();
if (size_src != size_dst)
REALM_ASSERT(src_dictionary.contains(key) && dst_dictionary.contains(key));
Copy link
Contributor

Choose a reason for hiding this comment

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

Agreed.

@@ -989,14 +1021,55 @@ void RecoverLocalChangesetsHandler::operator()(const Instruction::Clear& instr)
ClearResolver(RecoverLocalChangesetsHandler* applier, Instruction::Clear& instr)
: RecoveryResolver(applier, instr, "Clear")
{
switch (instr.collection_type) {
case Instruction::CollectionType::Single:
break;
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this is actually REALM_UNREACHABLE ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

we could be recovering instructions from a client that did not generate the collection type, so we play safe (same in the InstructionApplier)

@@ -626,52 +626,68 @@ void RecoverLocalChangesetsHandler::copy_lists_with_unrecoverable_changes()
bool RecoverLocalChangesetsHandler::resolve_path(ListPath& path, Obj remote_obj, Obj local_obj,
Copy link
Contributor

Choose a reason for hiding this comment

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

agreed.

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.

Looks good-a lot of updates to support collections in mixed and it's good to see plenty of test coverage to help ensure it's working as expected.

@danieltabacaru danieltabacaru merged commit ea5c960 into master May 10, 2024
35 of 37 checks passed
@danieltabacaru danieltabacaru deleted the dt/client_reset_recovery_for_collections_in_mixed branch May 10, 2024 06:50
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jun 9, 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.

Client reset with recovery does not work for collections in mixed
4 participants