cardstack / ember-data-fastboot

Serializes and restores the ember-data store for fastboot
MIT License
52 stars 24 forks source link

Add support for query & relationship requests #12

Closed vkinelev closed 7 years ago

vkinelev commented 7 years ago

Fetching data with store.query('modelNeme, {}) always sends a request to a server, even objects are already in an Ember store. Thus it is harder to upgrade beforeModel/model/afterModel hooks to be compatible with Fastboot. The same issue with fetching relationships backed up with "links".

A possible solution is to store IDs of objects returned by each query in shoebox. Use this list of IDs to filter and sort records retrieved from Ember local store when ember data fetches objects in the browser. I assume that all needed objects should be in Ember store, because ember-data-fastboot already transfers the entire ember store from Fastboot to Browser via shoebox.

It could be explained with the follow snippet:

// ...store.js or adapter.js
query() {
  // requestPathWithQueryParams - acts as a key in shoebox
  if (isFastboot) {
    return this.ajax().then(objects => {
      // remember a list of IDs for this particular request 
      shoebox.put(requestPathWithQueryParams, objects.mapBy('id'));
      return objects;
    })
  } else {
    let existingListOfIdsForThisRequest = shoebox.retrieve(requestPathWithQueryParams);
    if (existingListOfIdsForThisRequest) {
      // Get all local objects, filter out objects which ID is not in the list
      // remembered during the Fastboot rendering, and finally sort in the same order
      // as in the list of ids.    
      existingObjects = this.peekAll(modelName).filter(...).sort(...)
      if (existingObjects.length === existingListOfIdsForThisRequest.length) {
        return existingObjects;
      // If we don't have all needed objects locally, we have to fetch them from the server
      } else {
        return this.ajax()
      }
    } else {
      // Fetch as usually 
      return this.ajax()
    }    
  }
}

Any thoughts?

MartinMalinda commented 7 years ago

I'd be best if some query caching would be available in Ember Data itself, otherwise, there's no clean way to implement this IMO. AFAIK, extending an adapter is problematic if the parent app already does it. Extending store could be safer but I'm not sure if that is a good way to go.

Some inspiration could also be found here : https://gitlab.com/ddag/ember-query-cache/blob/master/addon/services/store.js

vkinelev commented 7 years ago

Yes, this is a good point.