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

feat(background-fetching): Introduce isFetching in QueryState to handle refetch #1211

Merged
merged 2 commits into from
Aug 8, 2022

Conversation

trollepierre
Copy link
Contributor

@trollepierre trollepierre commented Aug 1, 2022

Context:

We want to persist data from Cozy-Client, inside a storage, in order to reuse them for next loading of the app (without send any request to Pouch / Stack). Redux-persist helps us to persist redux store.

However, when the data got rehydrated, the requests have already a fetchStatus "loaded", so they are not updated by Cozy-Client, because the data already existed.

That's why we used fetchPolicy, to refresh data older than a certain amount of hours / days.
However there are some drawbacks:

  • a delay value is totally arbitrary, so not reliable
  • when fetchPolicy is not respected, then the query is reexecuted, passing the fetchStatus to loading again, that make application displaying a Spinner, which is bad for User Experience.

This PR follows the same concept of background fetching from React Query (https://react-query.tanstack.com/guides/background-fetching-indicators & https://react-query.tanstack.com/guides/window-focus-refetching)

Implementation

  • a query has a loaded fetchStatus
  • this query is restarted (by another component or a rehydratation)
  • then the query keeps the loaded fetchStatus, the applicaations keep displaying the data, while the request got executing in background. A isFetching: true attribute is added inside the QueryState
  • When CozyClient finally load the data to the store, the application refreshes instantly with fresh data

This behavior should only concern React part of Cozy Client (useQuery, ObservableQuery). The client.query() should not implement this, because inside Node usage, we will have issues.

@trollepierre trollepierre changed the base branch from master to jsdoc-param-description August 1, 2022 15:40
Copy link
Contributor

@Crash-- Crash-- left a comment

Choose a reason for hiding this comment

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

Few remarks:

  • Maybe we should add a per query attribute to enable background Fetching. And maybe if this attribute is here, we should override the fetchPolicy?
  • Maybe we should add a global attribute to enable background fetching. I think we already have something to declare global error handler.

docs/react-integration.md Outdated Show resolved Hide resolved
docs/react-integration.md Outdated Show resolved Hide resolved
docs/react-integration.md Show resolved Hide resolved
packages/cozy-client/src/store/queries.js Outdated Show resolved Hide resolved
packages/cozy-client/src/utils.js Outdated Show resolved Hide resolved
@trollepierre
Copy link
Contributor Author

Few remarks:
Maybe we should add a per query attribute to enable background Fetching. And maybe if this attribute is here, we should override the fetchPolicy?
Maybe we should add a global attribute to enable background fetching. I think we already have something to declare global error handler.

Clear. I think it would be better for developer experience to control the backgroundFetching of each query. I would better go for the "per query attribute" (inside QueryOptions)

  • do you think we should support both options (the global attribute AND the "per query" attribute)?

@Crash--
Copy link
Contributor

Crash-- commented Aug 3, 2022

do you think we should support both options (the global attribute AND the "per query" attribute)?

I think we should follow what we have done for the onError callback: We can add it globally or having one per query (c5f65d3)

@trollepierre trollepierre force-pushed the refetch branch 3 times, most recently from 160e6ad to b338a48 Compare August 3, 2022 14:30
@trollepierre trollepierre marked this pull request as ready for review August 3, 2022 14:59
Base automatically changed from jsdoc-param-description to master August 4, 2022 11:58
backgroundFetching: true
})
expect(fetchPolicy).not.toHaveBeenCalled()
})
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm really not sure about that. fetch policy is useful for caching and to avoid fetch "spam" when rendering several components.

background fetching will be more used for refreshing data when they already exists.

It should not be one or the other. We should find a way to make them live together.

Maybe that, by default, background fetching should respect the fetch policy. If it returns false, then we should not run the query.

After that, we can create a plugin to force the background fetch, for instance, when giving the focus or something.

What is your opinion about this feature?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

After reconsideration:

I see 3 different features that can be totally independant:

  • fetchPolicies, exactly what you define above

  • backgroundFetching that handles queryState.fetchStatus + isFetching, to prevent the Spinner and the bad UX. Implemented in this PR, if I revert that change line 917 in CozyClient.js and update this test expect(fetchPolicy).toHaveBeenCalled()

  • forcingRefetch - or something called refetchOnWindowFocus in reactQuery, when giving the focus, when an app needs to refetch whatever the fetch policies.

I am pretty sure, the background fetching will make the fetchPolicies decrease. Maybe the forcingRefetch is not that urgent. Personally I think we should try to see how the 2 first features will collaborate, after considering implementing the forcingRefetch.

So I agree 100% with you.

…le refetch

We want to persist data from Cozy-Client, inside a storage, in order to reuse them for next loading of the app (without send any request to Pouch / Stack). Redux-persist helps us to persist redux store.

However, when the data got rehydrated, the requests have already a fetchStatus "loaded",  so they are not updated by  Cozy-Client, because the data already existed.

That's why we used fetchPolicy, to refresh data older than a certain amount of hours / days.
However there are somme drawbacks:
- a delay value is totally arbitrary, so not reliable
- when fetchPolicy is not respected, then the query is reexecuted, passing the fetchStatus to loading again, that make application displaying a Spinner, which is bad for User Experience.

This PR follows the same concept of background fetching from React Query (https://react-query.tanstack.com/guides/background-fetching-indicators & https://react-query.tanstack.com/guides/window-focus-refetching)

- a query has a loaded fetchStatus
- this query is restarted (by another component or a rehydratation)
- then the query keeps the loaded fetchStatus, the applicaations keep displaying the data, while the request got executing in background. A `isFetching: true` attribute is added inside the QueryState
- When CozyClient finally load the data to the store, the application refreshes instantly with fresh data

This behavior should only concern React part of Cozy Client (useQuery, ObservableQuery). The client.query() should not implement this, because inside Node usage, we will have issues.
Copy link
Contributor

@Crash-- Crash-- left a comment

Choose a reason for hiding this comment

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

Nice! I'll try it on a cozy app!

@Crash-- Crash-- merged commit cfeec8b into master Aug 8, 2022
@Crash-- Crash-- deleted the refetch branch August 8, 2022 07:11
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.

2 participants