From 755d9feda017bdda53f96212fd36689f19089127 Mon Sep 17 00:00:00 2001 From: Lee Maguire Date: Tue, 23 Jul 2024 15:38:43 +0100 Subject: [PATCH 1/2] Add ability to open a synced realm without sync configuration. --- CHANGELOG.md | 16 +++++ include/cpprealm/internal/bridge/realm.hpp | 2 + src/cpprealm/internal/bridge/realm.cpp | 4 ++ tests/sync/flexible_sync_tests.cpp | 75 ++++++++++++++++++++++ 4 files changed, 97 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b0a5ca74..a45cdd11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,19 @@ +NEXT_RELEASE Release notes (YYYY-MM-DD) +============================================================= + +### Fixed +* None + +### Enhancements +* Add `realm::db_config::enable_forced_sync_history()` which allows you to open a synced Realm + even if a sync configuration is not supplied. + +### Compatibility +* Fileformat: Generates files with format v24. Reads and automatically upgrade from fileformat v10. + +### Internals +* None + 2.2.0 Release notes (2024-07-22) ============================================================= diff --git a/include/cpprealm/internal/bridge/realm.hpp b/include/cpprealm/internal/bridge/realm.hpp index 38703d1e..2b5b9453 100644 --- a/include/cpprealm/internal/bridge/realm.hpp +++ b/include/cpprealm/internal/bridge/realm.hpp @@ -199,6 +199,8 @@ namespace realm::internal::bridge { void set_schema_version(uint64_t version); void set_encryption_key(const std::array&); void should_compact_on_launch(std::function&& fn); + /// Open the Realm using the sync history mode even if a sync configuration is not supplied. + void enable_forced_sync_history(); std::optional get_schema(); template diff --git a/src/cpprealm/internal/bridge/realm.cpp b/src/cpprealm/internal/bridge/realm.cpp index 845b4985..f6d39d08 100644 --- a/src/cpprealm/internal/bridge/realm.cpp +++ b/src/cpprealm/internal/bridge/realm.cpp @@ -309,6 +309,10 @@ namespace realm::internal::bridge { get_config()->should_compact_on_launch_function = std::move(fn); } + void realm::config::enable_forced_sync_history() { + get_config()->force_sync_history = true; + } + enum ::realm::client_reset_mode realm::config::get_client_reset_mode() const { return static_cast(get_config()->sync_config->client_resync_mode); } diff --git a/tests/sync/flexible_sync_tests.cpp b/tests/sync/flexible_sync_tests.cpp index 9f7c5cb6..1396583b 100644 --- a/tests/sync/flexible_sync_tests.cpp +++ b/tests/sync/flexible_sync_tests.cpp @@ -102,6 +102,81 @@ TEST_CASE("flexible_sync", "[sync]") { auto flx_sync_config2 = user.flexible_sync_configuration(); REQUIRE_THROWS(db(flx_sync_config2)); } + + SECTION("open synced realm without sync config") { + realm_path path; + auto user = app.login(realm::App::credentials::anonymous()).get(); + + { + auto flx_sync_config = user.flexible_sync_configuration(); + flx_sync_config.set_path(path); + auto synced_realm = db(flx_sync_config); + + auto update_success = synced_realm.subscriptions().update([](realm::mutable_sync_subscription_set &subs) { + subs.clear(); + }).get(); + CHECK(update_success == true); + CHECK(synced_realm.subscriptions().size() == 0); + + update_success = synced_realm.subscriptions().update([](realm::mutable_sync_subscription_set &subs) { + subs.add("foo-strings", [](auto &obj) { + return obj.str_col == "foo"; + }); + subs.add("foo-link"); + }) + .get(); + CHECK(update_success == true); + CHECK(synced_realm.subscriptions().size() == 2); + + synced_realm.get_sync_session()->wait_for_upload_completion().get(); + synced_realm.get_sync_session()->wait_for_download_completion().get(); + + synced_realm.write([&synced_realm]() { + AllTypesObject o; + o._id = 1; + o.str_col = "foo"; + synced_realm.add(std::move(o)); + }); + + synced_realm.get_sync_session()->wait_for_upload_completion().get(); + synced_realm.get_sync_session()->wait_for_download_completion().get(); + + synced_realm.refresh(); + auto objs = synced_realm.objects(); + CHECK(objs.size() == 1); + } + + { + auto local_config = realm::db_config(); + local_config.set_path(path); + local_config.enable_forced_sync_history(); + auto local_realm = realm::open(local_config); + auto s = local_realm.objects().size(); + CHECK(s == 1); + local_realm.write([&local_realm]() { + AllTypesObject o; + o._id = 2; + o.str_col = "foo"; + local_realm.add(std::move(o)); + }); + } + + { + auto flx_sync_config = user.flexible_sync_configuration(); + flx_sync_config.set_path(path); + auto synced_realm = db(flx_sync_config); + auto subs_size = synced_realm.subscriptions().size(); + CHECK(subs_size == 2); + + synced_realm.get_sync_session()->wait_for_upload_completion().get(); + synced_realm.get_sync_session()->wait_for_download_completion().get(); + + synced_realm.refresh(); + auto objs = synced_realm.objects(); + CHECK(objs.size() == 2); + } + } + } template From f158e50545dc088b34fa859fb197d16b72a3d63b Mon Sep 17 00:00:00 2001 From: Lee Maguire Date: Thu, 25 Jul 2024 09:38:02 +0100 Subject: [PATCH 2/2] Address comments --- include/cpprealm/internal/bridge/realm.hpp | 2 + include/cpprealm/networking/websocket.hpp | 2 +- src/cpprealm/networking/websocket.cpp | 2 +- tests/sync/flexible_sync_tests.cpp | 45 ++++++++++++---------- 4 files changed, 29 insertions(+), 22 deletions(-) diff --git a/include/cpprealm/internal/bridge/realm.hpp b/include/cpprealm/internal/bridge/realm.hpp index 2b5b9453..c7220b12 100644 --- a/include/cpprealm/internal/bridge/realm.hpp +++ b/include/cpprealm/internal/bridge/realm.hpp @@ -200,6 +200,8 @@ namespace realm::internal::bridge { void set_encryption_key(const std::array&); void should_compact_on_launch(std::function&& fn); /// Open the Realm using the sync history mode even if a sync configuration is not supplied. + /// This mode is used for opening a synced realm with a local realm config in the scenario + /// that you do not have a valid sync user object. void enable_forced_sync_history(); std::optional get_schema(); diff --git a/include/cpprealm/networking/websocket.hpp b/include/cpprealm/networking/websocket.hpp index 1e4ea988..5b0c232c 100644 --- a/include/cpprealm/networking/websocket.hpp +++ b/include/cpprealm/networking/websocket.hpp @@ -305,7 +305,7 @@ namespace realm::networking { configuration m_configuration; private: void initialize(); - std::unique_ptr<::realm::sync::SyncSocketProvider> m_provider; + std::shared_ptr<::realm::sync::SyncSocketProvider> m_provider; }; } diff --git a/src/cpprealm/networking/websocket.cpp b/src/cpprealm/networking/websocket.cpp index 76851891..5686c6c5 100644 --- a/src/cpprealm/networking/websocket.cpp +++ b/src/cpprealm/networking/websocket.cpp @@ -65,7 +65,7 @@ namespace realm::networking { auto user_agent_binding_info = std::string("RealmCpp/") + std::string(REALMCXX_VERSION_STRING); auto user_agent = util::format("RealmSync/%1 (%2) %3", REALM_VERSION_STRING, util::get_platform_info(), user_agent_binding_info); - m_provider = std::make_unique<::realm::sync::websocket::DefaultSocketProvider>(util::Logger::get_default_logger(), user_agent); + m_provider = std::make_shared<::realm::sync::websocket::DefaultSocketProvider>(util::Logger::get_default_logger(), user_agent); } std::unique_ptr default_socket_provider::connect(std::unique_ptr o, websocket_endpoint&& ep) { diff --git a/tests/sync/flexible_sync_tests.cpp b/tests/sync/flexible_sync_tests.cpp index 1396583b..f1142527 100644 --- a/tests/sync/flexible_sync_tests.cpp +++ b/tests/sync/flexible_sync_tests.cpp @@ -104,14 +104,12 @@ TEST_CASE("flexible_sync", "[sync]") { } SECTION("open synced realm without sync config") { - realm_path path; auto user = app.login(realm::App::credentials::anonymous()).get(); + std::string realm_path = user.flexible_sync_configuration().path(); { auto flx_sync_config = user.flexible_sync_configuration(); - flx_sync_config.set_path(path); auto synced_realm = db(flx_sync_config); - auto update_success = synced_realm.subscriptions().update([](realm::mutable_sync_subscription_set &subs) { subs.clear(); }).get(); @@ -119,61 +117,68 @@ TEST_CASE("flexible_sync", "[sync]") { CHECK(synced_realm.subscriptions().size() == 0); update_success = synced_realm.subscriptions().update([](realm::mutable_sync_subscription_set &subs) { - subs.add("foo-strings", [](auto &obj) { - return obj.str_col == "foo"; + subs.add("my-sub", [](auto &obj) { + return obj.str_col == "a" && obj._id > 500 && obj._id < 520; }); subs.add("foo-link"); }) .get(); CHECK(update_success == true); CHECK(synced_realm.subscriptions().size() == 2); - synced_realm.get_sync_session()->wait_for_upload_completion().get(); synced_realm.get_sync_session()->wait_for_download_completion().get(); + auto objs = synced_realm.objects(); + CHECK(objs.size() == 0); + synced_realm.write([&synced_realm]() { AllTypesObject o; - o._id = 1; - o.str_col = "foo"; + o._id = 501; + o.str_col = "a"; synced_realm.add(std::move(o)); }); + synced_realm.refresh(); synced_realm.get_sync_session()->wait_for_upload_completion().get(); synced_realm.get_sync_session()->wait_for_download_completion().get(); - - synced_realm.refresh(); - auto objs = synced_realm.objects(); + objs = synced_realm.objects(); CHECK(objs.size() == 1); } { auto local_config = realm::db_config(); - local_config.set_path(path); + local_config.set_path(realm_path); local_config.enable_forced_sync_history(); auto local_realm = realm::open(local_config); - auto s = local_realm.objects().size(); - CHECK(s == 1); + CHECK(local_realm.objects().size() == 1); local_realm.write([&local_realm]() { AllTypesObject o; - o._id = 2; - o.str_col = "foo"; + o._id = 502; + o.str_col = "a"; local_realm.add(std::move(o)); }); + // outside of subscription view, will be reverted once opened + // with a sync config. + local_realm.write([&local_realm]() { + AllTypesObject o; + o._id = 503; + o.str_col = "b"; + local_realm.add(std::move(o)); + }); + CHECK(local_realm.objects().size() == 3); } { auto flx_sync_config = user.flexible_sync_configuration(); - flx_sync_config.set_path(path); auto synced_realm = db(flx_sync_config); + CHECK(synced_realm.objects().size() == 3); auto subs_size = synced_realm.subscriptions().size(); CHECK(subs_size == 2); synced_realm.get_sync_session()->wait_for_upload_completion().get(); synced_realm.get_sync_session()->wait_for_download_completion().get(); - synced_realm.refresh(); - auto objs = synced_realm.objects(); - CHECK(objs.size() == 2); + CHECK(synced_realm.objects().size() == 2); } }