From aaf28177bb82352fe298c8be44253b731761b4c6 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Mon, 3 Dec 2018 15:10:12 -0800 Subject: [PATCH 1/2] Allow unsubscribing from a query without a Subscription --- src/sync/partial_sync.cpp | 17 +++++++++++++---- src/sync/partial_sync.hpp | 2 ++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/sync/partial_sync.cpp b/src/sync/partial_sync.cpp index 5a2bec632..e70d8ffc8 100644 --- a/src/sync/partial_sync.cpp +++ b/src/sync/partial_sync.cpp @@ -33,13 +33,10 @@ #include #include -namespace { -constexpr const char* result_sets_type_name = "__ResultSets"; -} - namespace realm { namespace _impl { +using namespace ::realm::partial_sync; void initialize_schema(Group& group) { @@ -507,6 +504,18 @@ void unsubscribe(Subscription& subscription) } } +void unsubscribe(Object&& subscription) +{ + REALM_ASSERT(subscription.get_object_schema().name == result_sets_type_name); + auto realm = subscription.realm(); + enqueue_unregistration(std::move(subscription), [=] { + // The partial sync worker thread bypasses the normal machinery which + // would trigger notifications since it does its own notification things + // in the other cases, so manually trigger it here. + _impl::PartialSyncHelper::get_coordinator(*realm).wake_up_notifier_worker(); + }); +} + Subscription::Subscription(std::string name, std::string object_type, std::shared_ptr realm) : m_object_schema(realm->read_group(), result_sets_type_name) { diff --git a/src/sync/partial_sync.hpp b/src/sync/partial_sync.hpp index 070b103e0..de25e6f5e 100644 --- a/src/sync/partial_sync.hpp +++ b/src/sync/partial_sync.hpp @@ -35,6 +35,7 @@ class Object; class Realm; namespace partial_sync { +static constexpr const char* result_sets_type_name = "__ResultSets"; struct InvalidRealmStateException : public std::logic_error { InvalidRealmStateException(const std::string& msg); @@ -107,6 +108,7 @@ RowExpr subscribe_blocking(Results const&, util::Optional name); /// The operation is performed asynchronously. Completion will be indicated by the /// `Subscription` transitioning to the `Invalidated` state. void unsubscribe(Subscription&); +void unsubscribe(Object&&); } // namespace partial_sync From 525acf1b0fd288affaab97153ce128b392516d7f Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Tue, 4 Dec 2018 13:42:57 -0800 Subject: [PATCH 2/2] Add a basic test and a short description of the new function --- src/sync/partial_sync.hpp | 6 ++++++ tests/sync/partial_sync.cpp | 14 ++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/sync/partial_sync.hpp b/src/sync/partial_sync.hpp index de25e6f5e..04c902223 100644 --- a/src/sync/partial_sync.hpp +++ b/src/sync/partial_sync.hpp @@ -108,6 +108,12 @@ RowExpr subscribe_blocking(Results const&, util::Optional name); /// The operation is performed asynchronously. Completion will be indicated by the /// `Subscription` transitioning to the `Invalidated` state. void unsubscribe(Subscription&); + +/// Remove a partial sync subscription. +/// +/// This is effectively just obj.row().move_last_over(), but the deletion is +/// performed asynchronously on the partial sync worker thread rather than +/// the current thread. The object must be an object in the ResultSets table. void unsubscribe(Object&&); } // namespace partial_sync diff --git a/tests/sync/partial_sync.cpp b/tests/sync/partial_sync.cpp index 88f419e30..fd8280c88 100644 --- a/tests/sync/partial_sync.cpp +++ b/tests/sync/partial_sync.cpp @@ -489,6 +489,20 @@ TEST_CASE("Partial sync", "[sync]") { EventLoop::main().run_until([&] { return partial_sync_done; }); } + SECTION("named query can be unsubscribed by looking up the object in the Realm") { + auto subscription = subscription_with_query("number != 1", partial_config, "object_a", "query"s); + EventLoop::main().run_until([&] { return subscription.state() == partial_sync::SubscriptionState::Complete; }); + + auto realm = Realm::get_shared_realm(partial_config); + auto table = ObjectStore::table_for_object_type(realm->read_group(), partial_sync::result_sets_type_name); + ObjectSchema object_schema(realm->read_group(), partial_sync::result_sets_type_name); + size_t row = table->find_first(table->get_column_index("name"), StringData("query")); + Object subscription_object(realm, object_schema, table->get(row)); + + partial_sync::unsubscribe(std::move(subscription_object)); + EventLoop::main().run_until([&] { return subscription.state() != partial_sync::SubscriptionState::Complete; }); + } + SECTION("clearing a `Results` backed by a table works with partial sync") { // The `ClearTable` instruction emitted by `Table::clear` won't be supported on partially-synced Realms // going forwards. Currently it gives incorrect results. Verify that `Results::clear` backed by a table