Skip to content

Conversation

@vmoroz
Copy link
Member

@vmoroz vmoroz commented Jan 15, 2021

This PR addressed the issue described in #6836 and #6840.

The ReactNotificationService is used to send notifications between native modules, and between native modules and the app.
To provide automatic unsubscription on instance unload for all subscriptions created in native modules, we have implemented parent-child relationship between the ReactNotificationService ("parent") created in ReactNativeHost::InstanceSettings and in the ReactContext ("child"). The issue was that while notifications from the "child" service is propagated to the "parent", there was no mechanism to propagate them from the "parent" to "children".

In this PR we fix the issue. While we keep the same parent-child relationship, we change the way the notifications are sent and how we subscribe to them:

  • All notifications are sent from the "root" service - the topmost "parent" service. SendNotification
    method called on the "child" service just calls "parent" service's SendNotification method.
  • Subscriptions are added to services on all levels: a subscription added to a "child" service is also
    added to the "parent" service.
  • When "child" subscription is removed, it also removes the corresponding subscription in the
    "parent" service.

Other related changes in this PR:

  • Implemented NotificationBetweenAppAndModule test to verify the new behavior.
  • Added IReactNotificationSubscription::NotificationService as a convenience property to be used in the notification handler.
  • Switched to use std::unordered_map from std::map to keep subscriptions. It should have a better perf.
  • Added ways to use implicitly explicit JSValue constructors in TestEventService and TestEvent .
Microsoft Reviewers: Open in CodeFlow

@vmoroz vmoroz requested a review from a team January 15, 2021 01:22
@vmoroz vmoroz requested a review from a team as a code owner January 15, 2021 01:22
};

// The ReactNotificationService manages notification subscriptions and sending messages.
// A notification service may have a parent notification service most for the automatic
Copy link
Member

Choose a reason for hiding this comment

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

can you clarify what this means? most what?

// The ReactNotificationService manages notification subscriptions and sending messages.
// A notification service may have a parent notification service most for the automatic
// unsubscription when the notification service is deleted.
// All notifications are always sent from the root notification service that doe snot have parent service.
Copy link
Member

Choose a reason for hiding this comment

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

typo

@vmoroz vmoroz requested a review from asklar January 15, 2021 02:36
// method called on the "child" service just calls "parent" service's SendNotification method.
// - Subscriptions are added to services on all levels: a subscription added to a "child" service is also
// added to the "parent" service.
// - When "child" subscription is removed, it also removes the corresponding subscription in the
Copy link
Member

Choose a reason for hiding this comment

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

Do we have a risk of folks adding the same subscription to two nodes? i.e add it to root and then create a child to which it is added?
Of with the use of Lambda's to register the notifications that risk does not really exist... Or does the c++ parameterless lambda do some shared instance management?

Copy link
Member Author

@vmoroz vmoroz Jan 15, 2021

Choose a reason for hiding this comment

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

Each subscription is an object and it is unique. The Unsubscribe method is only available on the IReactNotificationSubscription object, and not on the IReactNotificationService. I.e. every time we call Subscribe method we create a unique subscription even if some of them have the same notification Id and the callback/lambda.

Copy link
Member

Choose a reason for hiding this comment

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

Sounds good, thanks!


In reply to: 557833370 [](ancestors = 557833370)

TestEventService::Initialize();

auto reactNativeHost =
TestReactNativeHostHolder(L"ReactNotificationServiceTests", [](ReactNativeHost const &host) noexcept {
Copy link
Member

Choose a reason for hiding this comment

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

I realize these are integration tests, should we have some unittests for this as well, especially to test things like:

  • subscribe, unsubscribe, subscribe
  • nested notification services etc
  • subscribing twice on the same node
  • subscribing twice on sibblings and then unsubscribe.
  • Error case for removing subscription twice?

Copy link
Member Author

Choose a reason for hiding this comment

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

Good point! Some of these tests are already there: see other tests in the same test file. I want to address the current issue as soon as possible, and I will address the additional test scenarios in another PR. I have created the issue #6881 for these items to be on my radar.

Copy link
Member

Choose a reason for hiding this comment

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

👍


In reply to: 557835279 [](ancestors = 557835279)

Copy link
Member

@dannyvv dannyvv left a comment

Choose a reason for hiding this comment

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

:shipit:

@vmoroz vmoroz added the AutoMerge Causes a PR to be automatically merged once all requirements are passed (label drives bot activity) label Jan 15, 2021
@ghost
Copy link

ghost commented Jan 15, 2021

Hello @vmoroz!

Because this pull request has the AutoMerge label, I will be glad to assist with helping to merge this pull request once all check-in policies pass.

Do note that I've been instructed to only help merge pull requests of this repository that have been opened for at least 10 hours, a condition that will be fulfilled in about 8 hours 11 minutes. No worries though, I will be back when the time is right! 😉

p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (@msftbot) and give me an instruction to get started! Learn more here.

@ghost ghost merged commit b703dd1 into microsoft:master Jan 15, 2021
vmoroz added a commit that referenced this pull request Jan 15, 2021
* Fix unused parameter warning in AbiCallInvoker (#6860)

* Move CallInvoker.h to TurboModule filter folder (#6861)

* Simplify Microsoft.ReactNative.IntegrationTests (#6868)

* Update clang-format version to 1.5.0 (#6870)

* Add JSValue constructor for std::optional<T> (#6873)

* Updated doc comments in IReactNotificationService.idl (#6875)

* Fix ReactNotificationService for notifications between app and modules (#6877)
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AutoMerge Causes a PR to be automatically merged once all requirements are passed (label drives bot activity)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants