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

chore: move entity loader utils into their own object #239

Merged
merged 1 commit into from
Jun 12, 2024

Conversation

wschurman
Copy link
Member

@wschurman wschurman commented Jun 5, 2024

Why

This is the second part of #238. From the summary:

In a follow-up, I'll look into moving the common methods (the ones in knownLoaderOnlyDifferences) to a different utils class since it no longer makes sense for them not to be on the loader class. But to limit the scope of this PR, they are kept in the NonEnforcingEntityLoader class for now.

This PR is this follow-up. It creates a utils concept that the loaders use but also that end-users can use in rare cases (we use them in rare cases in Expo server code).

The reason for this is that it doesn't make sense to have a call of the form (what they are after #238):
AssetEntity.loader(viewerContext, queryContext).nonEnforcing().invalidateEntityAsync(asset)

Instead, this PR makes it:
AssetEntity.loader(viewerContext, queryContext).utils().invalidateEntityAsync(asset)

Before both PRs, it was:
AssetEntity.loader(viewerContext, queryContext).invalidateEntityAsync(asset)

But I think it's better to not have them on the top-level loader for cleanliness.

Test Plan

Run all tests.

Copy link

codecov bot commented Jun 5, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 100.00%. Comparing base (2edc7af) to head (9d546c6).

Additional details and impacted files
@@            Coverage Diff            @@
##              main      #239   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           71        72    +1     
  Lines         1934      1949   +15     
  Branches       267       267           
=========================================
+ Hits          1934      1949   +15     
Flag Coverage Δ
integration 100.00% <100.00%> (ø)
unittest 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Member

@ide ide left a comment

Choose a reason for hiding this comment

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

From an API standpoint what makes you not want these methods on the top-level loader? When I think about the desired end state, loaders would be enforcing by default and most code would look like XEntity.loader(vc, qc).operation(). XEntity.loader(vc, qc).nonEnforcing().operation() would be the exception.

In terms of types, XEntity.loader(vc, qc) would conceptually return EnforcingLoader | Utils and XEntity.loader(vc, qc).nonEnforcing() would return just NonenforcingLoader.

@quinlanj
Copy link
Member

quinlanj commented Jun 10, 2024

I prefer AssetEntity.loader(viewerContext, queryContext).nonEnforcing().invalidateEntityAsync(asset) over AssetEntity.loader(viewerContext, queryContext).utils().invalidateEntityAsync(asset) because utils gives me no information about what is going on.

Most of the calls in www are of form AssetEntity.loader(viewerContext, queryContext).enforcing() anyways, so the user has to be aware of the Result concept and there is no reason to abstract it away with utils().

@wschurman
Copy link
Member Author

I think the reason I prefer them not be top-level is that they are so rarely used compared to loader methods, and shouldn't be used by normal applications except in exceptional cases. Some data from Expo backend:

  • ~1200 instances of loader methods
  • ~3 instances of invalidateEntityAsync calls
  • 2 instances of invalidateFieldsAsync, both in tests

So to me the API that makes the most sense in the end (for now, we can't put enforcing loader methods on top-level yet due to implicit breaking change) is:

  • Top-level loader has just three methods: enforcing, withAuthorizationResults, and utils (can be named something else)
  • Each of those loaders only has loadX methods (no invalidateEntityAsync).

@wschurman wschurman requested a review from ide June 11, 2024 19:41
Base automatically changed from @wschurman/non-enforcing-loader to main June 12, 2024 03:50
@wschurman wschurman force-pushed the @wschurman/non-enforcing-loader-2 branch from ea0bea9 to 9d546c6 Compare June 12, 2024 03:58
@wschurman
Copy link
Member Author

I prefer AssetEntity.loader(viewerContext, queryContext).nonEnforcing().invalidateEntityAsync(asset) over AssetEntity.loader(viewerContext, queryContext).utils().invalidateEntityAsync(asset) because utils gives me no information about what is going on.

This is a good point. "utils" in general is a pretty poor term. But in this case it's a bunch of utility methods that are both used by the loaders themselves as well as (super rarely) used by the application. They don't have a "enforcing" or "withAuthorizationResult" property (the methods in utils don't use results or throw errors or load entities), so in this case I think they belong elsewhere. And "utils" is all I got as far as creativity lol.

Most of the calls in www are of form AssetEntity.loader(viewerContext, queryContext).enforcing() anyways, so the user has to be aware of the Result concept and there is no reason to abstract it away with utils().

I think theres a slight misunderstanding in the set of methods being put in utils. It's just things like invalidateEntityAsync, but none of the load/result-based-load methods, those still live in their loaders.

So after this PR it is:

  • Entity.loader(vc, qc).enforcing().loadX: enforcing loader methods
  • Entity.loader(vc, qc).withAuthorizationResults().loadX: non-enforcing loader methods (wraps authorization and construction errors in Result)
  • Entity.loader(vc, qc).utils().invalidateEntityAsync: other methods related to loaders but very rarely used outside of loaders.

@wschurman wschurman merged commit 93905be into main Jun 12, 2024
2 checks passed
@wschurman wschurman deleted the @wschurman/non-enforcing-loader-2 branch June 12, 2024 04:04
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