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

[Hold for Payment on 16 June] Make permissions checking asynchronous by creating a withBetas HOC #3194

Closed
iwiznia opened this issue May 27, 2021 · 21 comments · Fixed by #3321
Assignees
Labels
Engineering Improvement Item broken or needs improvement. Weekly KSv2

Comments

@iwiznia
Copy link
Contributor

iwiznia commented May 27, 2021

If you haven’t already, check out our contributing guidelines for onboarding and email contributors@expensify.com to request to join our Slack channel!


Problem

The methods in permissions.js file should be asynchronous. They kind of already are if you look at the code, since data is coming from Onyx, but the methods themselves as synchronous, which does not align with how the data is loaded, so there are possible race conditions.

Solution

Change all places where permissions is used to instead subscribe to the ONYXKEYS.BETAS onyx key and call permissions methods passing the betas it got from onyx (see this comment)

Upwork posting - https://www.upwork.com/jobs/~01f29f2d2fa738d842

/cc @tgolen @marcaaron

@iwiznia iwiznia added AutoAssignerTriage Auto assign issues for triage to an available triage team member Engineering Improvement Item broken or needs improvement. labels May 27, 2021
@MelvinBot

This comment has been minimized.

@MelvinBot MelvinBot removed the AutoAssignerTriage Auto assign issues for triage to an available triage team member label May 27, 2021
@tgolen
Copy link
Contributor

tgolen commented May 27, 2021

Yeah, I think this is a good move. I'd like to see those moved to an HOC or at the very least be made asynchronous. Without them being asynchronous, we are limited by the amount of checks we can do. For example, we can't use Environment.getEnvironment() because that is an async method.

While this is not currently a problem, I'd like to change this code so that when new betas are added, they do not follow this old sync pattern anymore.

@iwiznia iwiznia added the Daily KSv2 label May 27, 2021
@marcaaron
Copy link
Contributor

marcaaron commented May 27, 2021

Gonna try to rephrase this problem solution to make sure I understand...

Problem

  • The beta list is fetched async then saved to storage before it updates the local list in memory.
  • We also use a native module to determine if the app version is beta which happens async.
  • Checks in Permissions.js need to wait for those things to happen before returning or else they may be inaccurate.

Solution

Make the Permissions methods async + create an HOC to delay rendering the wrapped component until after the async things are finished so we can check the betas via props?

Or was the HOC supposed to work differently...?

@iwiznia
Copy link
Contributor Author

iwiznia commented May 27, 2021

What do you mean by delay rendering? As in other HOCs, I think we would not delay it, right? If the betas data is not present, it would render the same as if you were not in any beta and when the data is available, it would re-render.

@marcaaron
Copy link
Contributor

As in other HOCs, I think we would not delay it, right? If the betas data is not present, it would render the same as if you were not in any beta and when the data is available, it would re-render.

withOnyx delays the rendering of a component until the data is retrieved from AsyncStorage so the Onyx.connect() part of our problem is already solved. That leaves the API call and the native modules async data.

Delaying came to mind since I'd assume we would not want to initialize a view with all beta features disabled by default and then flash in the beta features as the various data becomes available. But if we don't care about that then maybe another idea is to just subscribe directly to the betas key via withOnyx and update it with an action like...

let isOnDev;

function updateBetas(betas = []) {
    if (isOnDev) {
        Onyx.set(ONYXKEYS.BETAS, CONST.BETAS.ALL);
        return;
    }
    
    Onyx.merge(ONYXKEYS.BETAS, betas);
}

getEnvironment()
    .then((environment) => {
        isOnDev = environment === CONST.ENVIRONMENT.DEV;
        updateBetas();
    });

Now any component that is connected to withOnyx() can just pass this.props.betas to a Permissions.js method to check that feature.

render() {
    if (canUseChronos(this.props.betas)) {
        return (...)
    };
}

export default withOnyx({
    betas: {key: ONYXKEYS.BETAS}
})(SomeComponent);

@SofiedeVreese
Copy link
Contributor

I'm out of office today so removing my assignment and adding the AutoAssigner label back in for triaging.

@SofiedeVreese SofiedeVreese removed their assignment May 28, 2021
@SofiedeVreese SofiedeVreese added the AutoAssignerTriage Auto assign issues for triage to an available triage team member label May 28, 2021
@MelvinBot

This comment has been minimized.

@MelvinBot MelvinBot removed the AutoAssignerTriage Auto assign issues for triage to an available triage team member label May 28, 2021
@laurenreidexpensify

This comment has been minimized.

@tgolen
Copy link
Contributor

tgolen commented May 28, 2021

I think the delayed re-rendering might be a pre-optimization. I'm not sure that there is really a problem with that yet. However, I do kinda like the idea of just using withOnyx (not creating a new HOC) and then passing this.props.betas to the permission methods.

@iwiznia
Copy link
Contributor Author

iwiznia commented May 28, 2021

I kind of liked the HOC as it will abstract a common repeating pattern, but I am fine with subscribing to Onyx directly too.

@parasharrajat
Copy link
Member

I prefer Onyx solution, a pretty straightforward thing and no need of HOC overhead.

@iwiznia
Copy link
Contributor Author

iwiznia commented May 28, 2021

@laurenreidexpensify updated the OP, we are ready to move this forward, can you post it to upwork?

@MelvinBot
Copy link

Triggered auto assignment to @timszot (Exported), see https://stackoverflow.com/c/expensify/questions/7972 for more details.

@laurenreidexpensify
Copy link
Contributor

Upwork posting here https://www.upwork.com/jobs/~01f29f2d2fa738d842

@timszot timszot added Weekly KSv2 and removed Daily KSv2 labels Jun 1, 2021
@parasharrajat
Copy link
Member

parasharrajat commented Jun 1, 2021

Proposal

  1. We Will update all the methods in Permissions.js in a way that they take betas as a parameter.
    for example
function canUseAllBetas(betas) {
    return isDevelopment() || _.contains(betas, CONST.BETAS.ALL);
}
  1. Now we will pass the betas at all places where we are calling these methods.
  2. We will get the betas from Onyx by subscribing over the components as it makes the process synchronous.
    for ex:
withOnyx({
    betas: {key: ONYXKEYS.BETAS}
})(SomeComponent);

then updating the call as to Permissions.canUseAllBetas(this.props.betas) .

One of the location for change is https://github.com/Expensify/Expensify.cash/blob/f1cfb9eb102259a8f7f8662c86a432a09c23eb8e/src/pages/home/report/ReportActionCompose.js#L400

Special Case https://github.com/Expensify/Expensify.cash/blob/71c58ee8b17fce1503a8c9cabfcdc630b6fc5d2f/src/libs/OptionsListUtils.js#L336

Solution for this particular case.
  1. Subscribe to ONYXKEYS.BETAS at page level(SearchPage).
  2. Modify the getOptions to accept betas as optional Config Param
function getOptions(reports, personalDetails, draftComments, activeReportID, {
        betas = [],
        ....

which will be used at https://github.com/Expensify/Expensify.cash/blob/71c58ee8b17fce1503a8c9cabfcdc630b6fc5d2f/src/libs/OptionsListUtils.js#L336

  1. Modify getSearchOptions to take another parameter betas.
    https://github.com/Expensify/Expensify.cash/blob/71c58ee8b17fce1503a8c9cabfcdc630b6fc5d2f/src/libs/OptionsListUtils.js#L365
  2. pass down the betas from getSearchOptions to getOptions config key betas

@laurenreidexpensify laurenreidexpensify added Weekly KSv2 and removed Weekly KSv2 labels Jun 1, 2021
@laurenreidexpensify
Copy link
Contributor

@timszot these remain daily until we have a PR up and merged 👍🏽

@tgolen
Copy link
Contributor

tgolen commented Jun 1, 2021

@parasharrajat I think that sounds like a good proposal, but please take a look at this usage: https://github.com/Expensify/Expensify.cash/blob/71c58ee8b17fce1503a8c9cabfcdc630b6fc5d2f/src/libs/OptionsListUtils.js#L336

It is going to be the most difficult one since the betas will have to be passed down through several layers. Can you please update your proposal to include this? Thanks!

@parasharrajat
Copy link
Member

parasharrajat commented Jun 1, 2021

@tgolen
Better approach would be use the Onyx.connect method to pass the betas to getOptions but that goes against the desired behavior. We want to wait until betas is ready on Onyx so subscribing at component level helps but Onyx.connect will not.
So we can do the following:

  1. Subscribe to ONYXKEYS.BETAS at page level(SearchPage).
  2. Modify the getOptions to accept betas as optional Config Param
function getOptions(reports, personalDetails, draftComments, activeReportID, {
        betas = [],
        ....

which will be used at https://github.com/Expensify/Expensify.cash/blob/71c58ee8b17fce1503a8c9cabfcdc630b6fc5d2f/src/libs/OptionsListUtils.js#L336

  1. Modify getSearchOptions to take another parameter betas.
    https://github.com/Expensify/Expensify.cash/blob/71c58ee8b17fce1503a8c9cabfcdc630b6fc5d2f/src/libs/OptionsListUtils.js#L365
  2. pass down the betas from getSearchOptions to getOptions config key betas

@tgolen
Copy link
Contributor

tgolen commented Jun 1, 2021 via email

@laurenreidexpensify
Copy link
Contributor

@parasharrajat have hired you in Upwork 👍🏽

@laurenreidexpensify laurenreidexpensify changed the title Make permissions checking asynchronous by creating a withBetas HOC [Hold for Payment on 16 June] Make permissions checking asynchronous by creating a withBetas HOC Jun 9, 2021
@laurenreidexpensify laurenreidexpensify added Weekly KSv2 and removed Daily KSv2 labels Jun 9, 2021
@laurenreidexpensify
Copy link
Contributor

Payment has been issued in Upwork @parasharrajat 😃

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Engineering Improvement Item broken or needs improvement. Weekly KSv2
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants