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

refactor(app): add test for shouldUseNotifications false to true #17870

Merged
merged 3 commits into from
Mar 25, 2025

Conversation

mjhuff
Copy link
Contributor

@mjhuff mjhuff commented Mar 25, 2025

Overview

EDIT: See discussion below. Woops, we were already covered. Will just merge in the testing.

#17853 fixes an issue when the shouldUseNotifications flag is initially false and then flips to true. We must also account for scenarios in which the caller repeatedly sets the shouldUseNotifications flag between false and true: we do not want to add a new callback to the store every time shouldUseNotifications is true, only if it is not in the store already. Note that the callback added to the store is memoized, so includes is a sufficient filter check here. Also, we don't need to remove the callback every time shouldUseNotifications becomes false: we remove the callback on dismount.

This fix currently doesn't impact our codebase, fortunately. The one spot shouldUseNotifications flips is a one-time false to true.

This PR also adds testing for the earlier fix in the linked PR.

Test Plan and Hands on Testing

  • Can't test in office, but easy to reason through.

Risk assessment

low

@mjhuff mjhuff requested review from sfoster1, SyntaxColoring and a team March 25, 2025 13:22
@mjhuff mjhuff requested a review from a team as a code owner March 25, 2025 13:22
@mjhuff mjhuff requested review from jerader and removed request for a team and jerader March 25, 2025 13:22
Copy link
Member

@sfoster1 sfoster1 left a comment

Choose a reason for hiding this comment

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

the memoization happens on the caller-side rather than here, right? we should probably have a comment on this function saying that the callback should be memoized so its identity is stable between calls from the same location.

Copy link
Contributor

@SyntaxColoring SyntaxColoring left a comment

Choose a reason for hiding this comment

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

Seems OK, but can you elaborate on this?

Also, we don't need to remove the callback every time shouldUseNotifications becomes false: we remove the callback on dismount.

if the bug was that flipping the feature flag on and off kept accumulating callbacks, isn't the problem that the callback wasn't being removed when the feature flag went off?

@mjhuff
Copy link
Contributor Author

mjhuff commented Mar 25, 2025

if the bug was that flipping the feature flag on and off kept accumulating callbacks, isn't the problem that the callback wasn't being removed when the feature flag went off?

No, the problem is that every time shouldUseNotifications flips to true (not strictly the feature flag), we call appShellListener, and we re-add the callback to the store regardless of whether or not it's already present.

If it flips to false, we don't have to remove it immediately, because when the component dismounts, the callback gets cleaned up. See L88.

shouldUseNotifications potentially flipping to true repeatedly is the issue.

@SyntaxColoring
Copy link
Contributor

I've looked more closely at the code and now I'm a little more confused.

I'm looking at this calling code. If I understand correctly:

  1. Suppose we start with shouldUseNotifications set to true and the subscription fully set up.
  2. Then shouldUseNotifications flips to false for any reason, including turning the feature flag off.
  3. useEffect() is triggered.
    1. The cleanup function runs, which should call appShellListener with isDismounting: true, which should remove the callback.
    2. The useEffect() body runs again with the new value of shouldUseNotifications and no-ops because it is false.
  4. shouldUseNotifications flips back to true for any reason, including turning the feature flag back on.
  5. useEffect() is triggered again.

Because step 3i happens before step 7, how can there still be a callback in the store when we reach step 7?

@mjhuff
Copy link
Contributor Author

mjhuff commented Mar 25, 2025

I've looked more closely at the code and now I'm a little more confused.

Ah, no, the useEffect does not trigger the cleanup when shouldUseNotifications is false. That's the catch: the return statement of a useEffect is only invoked on component dismount. Any mounted component will invoke the dismount logic exactly once and only once.

@SyntaxColoring
Copy link
Contributor

I've looked more closely at the code and now I'm a little more confused.

Ah, no, the useEffect does not trigger the cleanup when shouldUseNotifications is false. That's the catch: the return statement of a useEffect is only invoked on component dismount. Any mounted component will invoke the dismount logic exactly once and only once.

I don't think that's true?

My cleanup logic runs even though my component didn’t unmount

The cleanup function runs not only during unmount, but before every re-render with changed dependencies...

@mjhuff
Copy link
Contributor Author

mjhuff commented Mar 25, 2025

I don't think that's true?

Ah, yep thanks. You're correct.

I'll just merge the testing changes from this PR then 👍

@mjhuff mjhuff changed the title fix(app): prevent adding redundant notification callbacks on enabled state updates refactor(app): add test for shouldUseNotifications false to true Mar 25, 2025
Copy link
Contributor

@SyntaxColoring SyntaxColoring left a comment

Choose a reason for hiding this comment

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

Cool, thanks for looking into this. LGTM if CI passes.

@mjhuff
Copy link
Contributor Author

mjhuff commented Mar 25, 2025

Cool, thanks for looking into this. LGTM if CI passes.

Thanks for being patient with me. It's been a week 😅

@mjhuff mjhuff merged commit 6c06699 into edge Mar 25, 2025
30 checks passed
@mjhuff mjhuff deleted the app_fix-adding-same-cb-notifications branch March 25, 2025 16:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants