-
Notifications
You must be signed in to change notification settings - Fork 483
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
feat(@clayui/data-provider): dedupe concurrent requests #3138
Conversation
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit 2f15543:
|
9d38c84
to
2f15543
Compare
Pull Request Test Coverage Report for Build 4737
💛 - Coveralls |
break; | ||
} | ||
|
||
promise = CONCURRENT_PROMISES[url] = fetch(url, fetchOptions) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems odd to me to have two =
within the same expressing. Is this intended?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it is intended, I think its probably best to separate them into two separate expressions since it'd be easy to miss while reading through.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added this because we are unable to support when the link
API is a function, we are unable to know what the endpoint is. It just adds a reference point for both, do you think it's a problem?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking we should at least separate it into two separate declarations. Would this work?
promise = fetch( // ...
CONCURRENT_PROMISES[url] = promise
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, no problem. I will do this.
@@ -24,7 +24,7 @@ const ClayDataProviderWithVariablesAndStorage = () => { | |||
<div className="col-md-4"> | |||
<ClayDataProvider | |||
fetchPolicy={FetchPolicy.CacheFirst} | |||
link="https://rickandmortyapi.com/api/character" | |||
link="https://rickandmortyapi.com/api/character/" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How come you added this here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yeah, that was because it was causing a 302 (Temporary redirect to the address with /
), I added it to not see it anymore on the tab network 😁.
delete CONCURRENT_PROMISES[url]; | ||
|
||
throw error; | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can assume and use finally()
instead of repeating the delete
in both then()
and catch()
— all modern browsers support finally()
, and core-js (which we use as a polyfill for IE in portal) has supported it for a while.
(I think that, as a library, Clay should be following a bring-your-own-polyfill approach like I said here).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh yeah, I had forgotten about that method available on Promise
, thanks!
I do feel a little queasy about this deduping happening auto-magically. What if I have an end point called That's a contrived example, I know, but this change takes some control out of my hands about when/how things get fetched. (I could work around it in this example, by adding some random parameter on the end of the requests.) Do we have a real-world example of where the current behavior has caused problems? That would be helpful context to have. |
Yeah 🤔, that's a good point! I think we can provide a property in
I don't have a real use case yet just hypotheses but this is what I see happening in popular libs where I am researching, some examples:
|
For me that's a big sign that we shouldn't rush here (and also it's not clear to me why we're working on it):
The thing about |
Hey @wincent yeah, React Apollo has a lot more power to make those decisions I assume React Query and SWR is in the same direction. My idea is not to increase the surface, of course we can take the risk here but rather increase the value in I think we can wait for that as we don't have a case inside Liferay it's still likely that people won't notice this detail and maybe it's already happening 😁 |
Yeah, this also makes me re-think the need to add this quite yet. Perhaps we can leave this as "on hold" for now and address in the future as we see a need for it. Sidenote... |
No problem for me!
I would say the same if I were to think about this line of reasoning but the data provider is a complement that adds value to Clay, many of our components need data and we can design an API oriented to our cases, the other tools try to do a lot, dealing with HTTP, GraphQL... not that it's bad but I think we can do something very exciting here with the thoughts that I put in issues. It is probably something that we will work more on in our next Data to Table/List components where the idea is to facilitate the creation of these components in more high-level components. Uma coisa legal que gosto do DataProvider, ele é leve, configurações minimas, muito poderoso para reutilizar pela aplicação com os mecanismos de cache, retry... and I find it very simple to start and grow. |
I would love this now haha, I avoided commenting on it here for a few weeks... I'm working on the migration from Form to React and I had noticed a use case for that: we there loads several components to create the form, we need a data that searches the server for a list of all available fields that we can use because clients can also create their own fields. We have a component that is responsible for rendering the layout of the fields, which is used to build a form and is also used to edit the fields themselves, used in the Sidebar. The case is that this data is used only in the Field component, which is responsible for loading the fields on demand, as the migration is being little by little from the bottom up, there was no way to put the I can avoid this today, using cache policies and global storage to avoid another request when opening the Sidebar, but I ended up finding another problem with concurrent requests, we have a component that serves as compatibility to allow calling a specific component written in React in a part of the application that is still in Metal+Soy, with no provision to migrate that part yet... so anyway I go back to the problem, I have to add a An option here also: initializes the application already with this data, but we do not want to touch the applications they are using, because it is used in other modules and we will need to reuse the servlet that does this... But I'll leave that decision to the team 😁, They still need to "put their own house in order"! |
I think it's great that you have needs emerging out of first-hand experience trying to get things done @matuzalemsteles. That's going to lead us to a better design for sure. |
Yeah, it sure has great value. |
@matuzalemsteles since this update will likely be moved over to the dxp specific implementation of data-provider, I am going to close this PR. If if needs to be reopened in the future, just let me know! |
This dedup of concurrent requests to the same address, this is for cases when the same component is displayed twice on the screen, a strategy that the application does to mitigate this is to move to above of component with useResource state, but now it is not more necessary because we have normalized everything, it makes the experience more comfortable for the developer.
I think this is part of other details that I want to implement in the data provider to encourage good standards in dealing with the flow of data in the applications, using suspense, fetching early... I will work more on this after I am finished with the migration DDM-field-type... probably 😁!