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

[Notifications] Replace mutable map with Thread safe map for storing all active notifications #12655

Draft
wants to merge 7 commits into
base: trunk
Choose a base branch
from

Conversation

AnirudhBhat
Copy link
Contributor

@AnirudhBhat AnirudhBhat commented Sep 23, 2024

Closes: #12654

Description

While fixing ConcurrencyModificationException #12646, we came to conclusion that replacing mutableMap with Thread safe map would benefit in the long run.

This PR:

  1. Renames ACTIVE_NOTIFICATIONS_MAP to activeNotificationsMap
  2. Replace mutableMap with ConcurrentHashMap
  3. Remove @Synchronized annotation from public methods in NotificationMessageHandler
  4. Remove unnecessary copy of a map
  5. Update test to handle all notification related public methods to verify it doesn't throw ConcurrentModificationException

Testing information

I've tested this by ensuring unit test pass after making this change and fails if we revert this change. Please ensure the notifications flow isn't broken by this change.

  1. Make activeNotificationsMap mutableMap from ConcurrentHashMap
  2. Run handle notifications concurrently without throwing ConcurrentModificationException unit test
  3. Ensure the test fails
  4. Now, revert back activeNotificationsMap to ConcurrentHashMap
  5. Ensure the test passes now.
  • I have considered if this change warrants release notes and have added them to RELEASE-NOTES.txt if necessary. Use the "[Internal]" label for non-user-facing changes.

Reviewer (or Author, in the case of optional code reviews):

Please make sure these conditions are met before approving the PR, or request changes if the PR needs improvement:

  • The PR is small and has a clear, single focus, or a valid explanation is provided in the description. If needed, please request to split it into smaller PRs.
  • Ensure Adequate Unit Test Coverage: The changes are reasonably covered by unit tests or an explanation is provided in the PR description.
  • Manual Testing: The author listed all the tests they ran, including smoke tests when needed (e.g., for refactorings). The reviewer confirmed that the PR works as expected on big (tablet) and small (phone) in case of UI changes, and no regressions are added.

@AnirudhBhat AnirudhBhat added type: task An internally driven task. feature: notifications Related to notifications or notifs. labels Sep 23, 2024
@AnirudhBhat AnirudhBhat added this to the 20.6 milestone Sep 23, 2024
@wpmobilebot
Copy link
Collaborator

📲 You can test the changes from this Pull Request in WooCommerce-Wear Android by scanning the QR code below to install the corresponding build.
App Name WooCommerce-Wear Android
Platform⌚️ Wear OS
FlavorJalapeno
Build TypeDebug
Commitb30300d
Direct Downloadwoocommerce-wear-prototype-build-pr12655-b30300d.apk

@wpmobilebot
Copy link
Collaborator

📲 You can test the changes from this Pull Request in WooCommerce Android by scanning the QR code below to install the corresponding build.

App Name WooCommerce Android
Platform📱 Mobile
FlavorJalapeno
Build TypeDebug
Commitb30300d
Direct Downloadwoocommerce-prototype-build-pr12655-b30300d.apk

@AnirudhBhat AnirudhBhat marked this pull request as draft September 23, 2024 05:33
@AnirudhBhat
Copy link
Contributor Author

AnirudhBhat commented Sep 23, 2024

@kidinov Converted this to draft as I realised that we need to maintain notification order for displaying it in group notifications and ConcurrentHashMap doesn't maintain insertion order. I need to think more about the solution and the risk of causing regression before coming up with the solution. I'm putting this PR on hold for now.

@kidinov
Copy link
Contributor

kidinov commented Sep 23, 2024

@AnirudhBhat 👋

I think this may work:
val map: MutableMap<String, Int> = Collections.synchronizedMap(LinkedHashMap())

@AnirudhBhat
Copy link
Contributor Author

In this case, we likely need to add a Synchronized block wherever we iterate over the map, which would be similar to our current solution but more complex and harder to read. What do you think?

@kidinov
Copy link
Contributor

kidinov commented Sep 24, 2024

@AnirudhBhat 👋

In this case, we likely need to add a Synchronized block wherever we iterate over the map

Not sure I am following. Why so?

@AnirudhBhat
Copy link
Contributor Author

Not sure I am following. Why so?

AFAIU, SynchronizedMap requires manual synchronisation when iterating over its map. The documentation says this as well.

I could confirm this by changing the notifications map to Collections.synchronizedMap(LinkedHashMap()) and running the unit test would fail.

Let me know if I'm missing something. Thanks!

@kidinov
Copy link
Contributor

kidinov commented Sep 24, 2024

AFAIU, SynchronizedMap requires manual synchronisation when iterating over its map. The documentation says this as well.

My understanding of the documentation is that you need to sync on the map when you are iterating over anything that returned from it, e.g iterator, keys etc

Having said that, I looked up the code, and I don't understand where we need an insertion order. Could you please point me out?

Also, do you understand why asSequence put everywhere?

@AnirudhBhat
Copy link
Contributor Author

Having said that, I looked up the code, and I don't understand where we need an insertion order. Could you please point me out?

  1. We use mutableMap which internally uses LinkedHashMap that maintains insertion order
  2. There are few tests that verify insertion order along with others
    when two new order notifications are received for different stores display the notification correctly
    when two new review notifications are received for the same store, then display the notification correctly
    when two new order notifications are received for the same store, then display the notification correctly

and few more

Also, do you understand why asSequence put everywhere?

I'm not sure. Maybe for performance gains?

@kidinov
Copy link
Contributor

kidinov commented Sep 25, 2024

@AnirudhBhat 👋

We use mutableMap which internally uses LinkedHashMap that maintains insertion order
Yep, I got that; the question is if we need to maintain insertion order. I can not find that in the code - seems all reads are by id 🤔

There are few tests that verify insertion order along with others

I tried to change the implementation of the map to ConcurrentHashMap -> when two new order notifications are received for the same store, then display the notification correctly. Spent some time - could not figureout what exactly the test tests though 😀

I'm not sure. Maybe for performance gains?

In most cases, there is no performance gain, though, as we just iterate over the map. In a couple of places we filter so it'll give minimal performance, but we probably talking about a few notifications here so probably negletable

@wpmobilebot wpmobilebot modified the milestones: 20.6, 20.7 Sep 27, 2024
@wpmobilebot
Copy link
Collaborator

Version 20.6 has now entered code-freeze, so the milestone of this PR has been updated to 20.7.

@wpmobilebot wpmobilebot modified the milestones: 20.7, 20.8, 20.9 Oct 11, 2024
@wpmobilebot
Copy link
Collaborator

Version 20.8 has now entered code-freeze, so the milestone of this PR has been updated to 20.9.

@wpmobilebot wpmobilebot modified the milestones: 20.9, 21.0 Oct 25, 2024
@wpmobilebot
Copy link
Collaborator

Version 20.9 has now entered code-freeze, so the milestone of this PR has been updated to 21.0.

@wpmobilebot wpmobilebot modified the milestones: 21.0, 21.1 Nov 1, 2024
@wpmobilebot
Copy link
Collaborator

Version 21.0 has now entered code-freeze, so the milestone of this PR has been updated to 21.1.

@wpmobilebot wpmobilebot modified the milestones: 21.1, 21.2 Nov 8, 2024
@wpmobilebot
Copy link
Collaborator

Version 21.1 has now entered code-freeze, so the milestone of this PR has been updated to 21.2.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature: notifications Related to notifications or notifs. type: task An internally driven task.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Notifications] Replace mutable map with Thread safe map for storing all active notifications
3 participants