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
REST query pagination #3962
REST query pagination #3962
Conversation
…trol props in order to avoid triggering additional reactive statements and improve performance
…n initial props without triggering svelte invalidation
…sources to new DataFetch model
…s as case-insensitive
…e into rest-pagination
…e into rest-pagination
… in new data fetch model
…e into rest-pagination
…it will be replaced
Incredible write-up @aptkingston and awesome work. I look forward to trying the new Rest connector. Perf improvements are starting to become the norm with your PRs! |
Codecov Report
@@ Coverage Diff @@
## develop #3962 +/- ##
===========================================
+ Coverage 68.89% 68.91% +0.02%
===========================================
Files 139 139
Lines 4630 4633 +3
Branches 685 685
===========================================
+ Hits 3190 3193 +3
- Misses 1017 1018 +1
+ Partials 423 422 -1
Continue to review full report at Codecov.
|
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.
LGTM! Some really nice refactoring in here and great to see the server tests as well
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.
LGTM - great job. The datadfetch abstraction is super clean - should make it so much easier going forward. I pulled it down and had a play around with an app I was trying to build that needed pagination. Works flawlessly 👌
Description
This PR adds pagination to REST queries.
It also includes a full rewrite of data fetching inside client apps, and significant performance improvements.
REST query pagination
Pagination has a few different configuration options:
Pagination is configured in a new tab for REST queries:
When pagination is configured, a pagination control will appear as normal for REST query data providers which have pagination enabled. The client experience is identical to pagination for internal tables or datasource plus tables.
When pagination parameters are configured to be sent in the request body, it will use the body type configured in the
Body
tab. Not all body types are supported - for example it is not possible to add pagination parameters to a raw text body. The supported body types are:If you set up a query to be a POST request with a body type other than the specified ones, and then also configure pagination parameters to be send in the request body, then pagination will be ignored and will not be applied. It will also be ignored if you configure a GET request but then specify that pagination should be included in the request body. Just be sensible basically.
Client data fetching rewrite
As part of this work, the entire process of fetching data in client apps needed to be written. Previously pagination was a concept that was entirely scoped to internal tables or datasource plus tables, and was handled in an opionated manner by the search endpoint. This work introduced the requirement of queries needing to support pagination, and for that pagination to be flexible and configurable.
The client library now has a new base class implementation for fetching data from a datasource called
DataFetch
. This class is extrended and customised to handle the different types of core datasource:TableFetch
ViewFetch
RelationshipFetch
QueryFetch
There are also implementations for the more client focused "fake" datasources:
NestedProviderFetch
FieldFetch
JSONArrayFetch
These new models do not consider the previous binary concept of "plus" and "non plus" datasource - they only consider what features any given datasource supports. Those features are searching, sorting and pagination. Each implementation defines which features are supported as well as how to fetch the datasources data and schema. If a certain datasource does not support searching or sorting then a client side implementation will be used, transparently ensuring that all sources support these features. Currently there is not a client side implementation for pagination, but this could potentially be added if required.
Eventualy this new implementation of data fetching will become the core implementation used in the builder as well.
Client library optimisations (in depth dev notes for reference)
While implementing the data fetching rewrite it became apparent that reactive statements in client components were triggering more often than they should. I did a very deep dive into svelte internals to work out why this is happening. It turns out that due to how we pass in props to components (we store all props inside an object and spread them in
{ ...props }
which we have to do because everything is generic), any non-primitive props (such as objects) trigger a svelte invalidation whenever any other prop is changed.Consider the following props:
and consider the following component:
If the
count
prop changes, even by direct mutation of the object and not touchingfoo
in any away:Then our reative statement inside our component will fire. This is terrible for performance of our components, as any prop change will trigger an invalidation of any other non-primitive props. Unfortunately the solution to this is non-trivial because this is just how svelte works.
I did find a solution to this problem by using the underlying svelte
$$set
function which exists on component refs. Using this function allows you to directly mutate a certain prop without invalidating other props. There are other considerations with using this approach, such as how to handle the initial render and how to avoid stale props, which have all been addressed. The new implementation for managing client component props can be seen inComponent.svelte
.The result of this work is that whenever any props change, only the actual prop that changed is invalidated (as if we were a real app, and not a generic app created at runtime). This means that we immediately benefit from the following:
Misc fixes
KeyValueBuilder
that happened whenobject
was explicity set tonull