Skip to content

Reduce calls of the /featureFlag API#10859

Merged
danjm merged 17 commits intoMetaMask:developfrom
dan437:swaps-feature-flag
Apr 14, 2021
Merged

Reduce calls of the /featureFlag API#10859
danjm merged 17 commits intoMetaMask:developfrom
dan437:swaps-feature-flag

Conversation

@dan437
Copy link
Contributor

@dan437 dan437 commented Apr 9, 2021

Explanation

Instead of periodically checking if the Swaps feature is enabled every 10 minutes, we will check it only when a user enters the Swaps feature. That will dramatically decrease calls to the /featureFlag API.

Manual testing steps

Feature is enabled:

  • Open the MetaMask extension
  • You should see the "Swap" button every time now
  • Click on the "Swap" button
  • Page for showing the Swaps feature is displayed immediately
  • A user selects From and To tokens and is able to successfully swap them

Feature is enabled - loaded from 10 min cache without any API call to the /featureFlag API:

  • Finish the first test case ("Feature is enabled")
  • Open the MetaMask extension
  • You should see the "Swap" button every time now
  • Click on the "Swap" button
  • Page for showing the Swaps feature is displayed immediately, API call to the /featureFlag API is loaded from our 10 min cache and a user is still on the Swaps page
  • A user selects From and To tokens and is able to successfully swap them

Feature is disabled:

  • In ui/app/ducks/swaps/swaps.js -> fetchSwapsLiveness dispatch and return false
  • Open the MetaMask extension
  • You should see the "Swap" button every time now
  • Click on the "Swap" button
  • Page for showing the Swaps feature is displayed immediately with a disabled "Review Swap" button
  • The "Offline for maintenance" error page is displayed almost immediately after the /featureFlag call is done
  • A user can click on the "Close" button / Cancel or the Fox head, get back to the main page and try again. However, we cache responses for 10 minutes, so they will need to wait a bit before trying again

Screenshots

Swap button is always visible now:
image

Swap page is accessible immediately by default:
image

Show the "Offline for maintenance" page if the Swaps feature is disabled:
image

@dan437 dan437 requested a review from a team as a code owner April 9, 2021 00:34
@dan437 dan437 requested a review from darkwing April 9, 2021 00:34
@github-actions
Copy link
Contributor

github-actions bot commented Apr 9, 2021

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

Copy link
Member

Choose a reason for hiding this comment

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

It looks like this loading screen is only shown once, the first time the user clicks 'swaps'. On subsequent navigations to the swaps page, it will show the maintenance page or the build quote page immediately while it checks the API liveness in the background.

Was this intended? At the very least it's probably worth showing the loading screen if the last check showed the API as down.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I had the same thought as you at first, but we actually clean up a Swaps state by calling the prepareToLeaveSwaps function from various places, e.g. here: https://github.com/MetaMask/metamask-extension/blob/develop/ui/app/pages/swaps/index.js#L178
prepareToLeaveSwaps calls the resetBackgroundSwapsState function and that one calls resetSwapsState every time a user leaves the Swaps feature. That will set the isFeatureFlagLoaded flag to false.

I've just tried this by going back by 3 different ways: clicking on Cancel, clicking on the Fox head and clicking on the "Close" button on the "Offline for maintenance" page and then every time I click on "Swaps" from the main page, I can see the page loader again.

Copy link
Member

Choose a reason for hiding this comment

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

Huh, I hadn't realized. Good to know!

Copy link
Member

Choose a reason for hiding this comment

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

Does this need to be background state? 🤔 It seems to only be used in one UI component. Maybe it could be migrated to component state - set to false when the component mounts, and true when the fetchSwapsLiveness call resolves. That would make it easier to use the loading screen in more cases as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's right that it's only used in one UI component. What do you think about my code below? I'm using a recommended way to make async calls from the useEffect function: https://stackoverflow.com/questions/53332321/react-hook-warnings-for-async-function-in-useeffect-useeffect-function-must-ret

const [isFeatureFlagLoaded, setIsFeatureFlagLoaded] = useState(false);

useEffect(() => {
    const fetchSwapsLivenessWrapper = async () => {
      await dispatch(fetchSwapsLiveness());
      setIsFeatureFlagLoaded(true);
    };
    fetchSwapsLivenessWrapper();
  }, []);

Copy link
Member

Choose a reason for hiding this comment

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

useEffect certainly seems appropriate!

The pattern you're using here with a "wrapper" function seems a bit odd. I don't follow what the wrapper is for 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Without it React shows a warning:
image

When I use the wrapper, no warning :)

Copy link
Member

Choose a reason for hiding this comment

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

Got it, that makes sense.

Copy link
Contributor

@darkwing darkwing left a comment

Choose a reason for hiding this comment

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

Marking as "request changes" due to some UX improvements that need to be made around disabling the button and avoiding the spinner.

Looks great so far @dan437 !

@danjm
Copy link
Contributor

danjm commented Apr 13, 2021

Only one last small comment:

I think we should add a const swapsFeatureLiveness = useSelector(getSwapsFeatureLiveness) to build-quote.js, and disable the button if swapsFeatureLiveness is falsey. I know this usually won't matter because the api call will usually resolve before the user fills out the form. But what if the user is really really fast?

In any case, our intent is that the user should not be able to click the "Review Swap" button until the call to the /featureFlag api is resolved. So it would be good to communicate that intent in the code.

@dan437
Copy link
Contributor Author

dan437 commented Apr 13, 2021

Hi @danjm, so, if swapsFeatureLiveness is false, the build-quote.js is discarded and the error page is rendered instead. That is controlled from the swaps/index.js file. However, I started passing the isFeatureFlagLoaded prop to build-quote.js and disable the button if the feature flag hasn't been properly loaded yet. I've tried to do a happy path after this change and I'm able to swap tokens successfully.
image

@danjm danjm dismissed darkwing’s stale review April 14, 2021 07:16

David's comment was addressed

@danjm danjm merged commit e7d7d24 into MetaMask:develop Apr 14, 2021
@github-actions github-actions bot locked and limited conversation to collaborators Apr 14, 2021
@dan437 dan437 deleted the swaps-feature-flag branch July 24, 2023 11:28
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants