Skip to content

Issue with offset #230

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

Closed
jmdobry opened this issue Nov 7, 2014 · 6 comments
Closed

Issue with offset #230

jmdobry opened this issue Nov 7, 2014 · 6 comments
Assignees
Labels

Comments

@jmdobry
Copy link
Member

jmdobry commented Nov 7, 2014

There is a problem with offset:
Suppose that resource has no injected items, then by calling

DS.findAll('resource', {offset: 10, limit: 10})

we will get requested items injected to data store and our query cached. But if we call the same code again, the DS.filter function kicks in and will offset these 10 items in data store, thus returning empty array.

See also #76

@jmdobry jmdobry added the bug label Nov 7, 2014
@jmdobry jmdobry self-assigned this Nov 7, 2014
@aikoven
Copy link

aikoven commented Nov 9, 2014

One possible solution would be to store returned items by params hash alongside resource.completedQueries and return them from DS.findAll instead of calling DS.filter. A shortcoming of this approach is when offset is not a multiple of limit, we'd potentially get lots of cached arrays with lots of duplicate elements between them.

Another idea is to store offset value for each {where: ..., orderBy: ...} object for each item based on its index in returned array. Although it leads to much more complicated work to build an array from cache, this approach makes DS.filter and DS.findAll truly consistent.

@jmdobry
Copy link
Member Author

jmdobry commented Jan 10, 2015

I fixed this in js-data, so it will be available in js-data-angular (angular-data 2.0).

See js-data/js-data#30

@jmdobry jmdobry closed this as completed Jan 10, 2015
@jmdobry
Copy link
Member Author

jmdobry commented Jan 10, 2015

One possible solution would be to store returned items by params hash alongside resource.completedQueries and return them from DS.findAll instead of calling DS.filter.

That was the solution.

@aikoven
Copy link

aikoven commented Mar 7, 2015

I've ran against an issue with this solution, when new items are added to storage, DS.findAll would still return old items. Also when item is ejected from storage, we only remove item from query data, although we should probably flush queryData completely. Here's an example:

Suppose that resource has 10 items on the server.

DS.findAll('resource', {limit: 5})  // get first 5 items
// ...
DS.eject('resource', 0)  // eject one item
DS.findAll('resource', {limit: 5})  // this will return 4 items instead of 5

@aikoven
Copy link

aikoven commented Mar 7, 2015

We can still optimise this a bit and only flush queryData when added/removed/changed item meets query criteria.

@jmdobry
Copy link
Member Author

jmdobry commented Mar 7, 2015

Here's how it works (assuming default settings). If the server has 10 items, then:

  1. DS.findAll('resource', { limit: 5 }) // Injects 5 items into the store, and "remembers" that those particular 5 items were returned by the server for the "{limit:5}" query.
  2. DS.findAll('resource', { limit: 5 }) // Resolves with whatever was cached for the "{limit:5}" query.
  3. DS.findAll('resource', { limit: 5 }, { useFilter: true }) // Instead, delegate to DS#filter, passing it the params arg that was just passed to DS#findAll. Resolve with the result of the DS#filter call.
  4. DS.eject('resource', 0) // Remove an item from the store, also removing it from any cached queries the item appears in. Any cached queries whose associated list of data becomes empty because of this action are automatically flushed/invalidated, otherwise, the store just assumes the updated cached query is what would be returned by the server if the query were to be made again.
  5. DS.findAll('resource', { limit: 5 }) // Resolves with whatever was cached for the "{limit:5}" query (now 4 items).
  6. DS.findAll('resource', { limit: 5 }, { useFilter: true }) // Instead, delegate to DS#filter, passing it the params arg that was just passed to DS#findAll. Resolve with the result of the DS#filter call (now 4 items).

Now, you can manually eject the remaining items and the cached query with be flushed/invalidated.

Or you can manually flush the query by doing this:

// Force a new query to be made
DS.findAll('resource', { limit: 5 }, { bypassCache: true })

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants