ember-sync icon indicating copy to clipboard operation
ember-sync copied to clipboard

Find records from offline store, then from online store only if not found

Open Leooo opened this issue 9 years ago • 2 comments

Small piece of code for this, use

this.emberSync.findOfflineFirst('posts');

or

this.emberSync.findOfflineFirst('post','27');

to get a promise filled with offline store results if any (without fetching the server), otherwise online store results fetched from the server. This can be useful if we want to use localStorage as a cache of user's own data, and reduce the number of requests to the server for records which can only be modified by the user (while still being able to send changes to the server):

import EmberSync from 'ember-sync';
import StoreInitMixin from "ember-sync/store-initialization-mixin";
import Persistence from "ember-sync/persistence";
import Query from 'ember-sync/query';
import Ember from 'ember';

var alreadyRun=false;

export default {
  name: 'override-ember-sync',
  before: 'store',
  initialize: function() {
    if (alreadyRun) {
      return;
    } else {
      alreadyRun=true;
    }

    EmberSync.reopen(StoreInitMixin,{
      findOfflineFirst: function(type, query) {
        var _this = this;
        var syncQuery = Query.create({
          onlineStore:  this.onlineStore,
          offlineStore: this.offlineStore,
          onError:      this.get('onError'),
          onRecordAdded:     function(record) {
            _this.onRecordAdded(record, type);
          }
        });
        return syncQuery.findOfflineFirst(type, query);
      },
    });

    Query.reopen({
      findOfflineFirst: function(type, query) {
        var _this=this;
        var offlineSearch = Ember.isNone(query) ? _this.offlineStore.findAll(type) : _this.offlineStore.find(type, query);
        return new Ember.RSVP.Promise(function(resolve, reject) {
          offlineSearch.then(function(record) {
              if (!record.toArray().length) {
                _this.findOnlineOnly(type, query).then(function(record){resolve(record);},
                                                       function(error){reject(error);});
              }
              else {
                //see https://github.com/kurko/ember-localstorage-adapter/issues/113
                record.forEach(function(rec){
                  if (record.get('id')) {
                    _this.onRecordAdded(record);
                  }
                });
                resolve(record);
              }
          },
          function(error) {
            _this.findOnlineOnly(type, query).then(function(record){resolve(record);},
                                                   function(error){reject(error);});
          });
        });
      },
      findOnlineOnly: function(type, query){
        var _this=this;
        var onlineSearch  = Ember.isNone(query) ? _this.onlineStore.findAll(type) : _this.onlineStore.find(type, query);
        return new Ember.RSVP.Promise(function(resolve, reject) {
          onlineSearch.then(function(record) {
              if (!record.toArray().length) {reject(record);}
              else{
                 record.forEach(function(rec){
                  var id = rec.get('id'),
                      persistenceState = _this.offlineStore.find(type, id);
                  var persistRecordOffline = function(onlineRecord) {
                    var persistence = Persistence.create({
                      onlineStore:  _this.onlineStore,
                      offlineStore: _this.offlineStore,
                    });
                    persistence.persistRecordOffline(type,rec);
                  };
                  persistenceState.then(persistRecordOffline, persistRecordOffline);
                  _this.onRecordAdded(rec);
                });
                resolve(record);
            }
          },function(error){
            reject(error);
          });
        });
      },
    });

  },
}

Leooo avatar Apr 11 '15 19:04 Leooo

Any chance you could write this as a PR, with some tests? That way we'd be able discuss line by line :D

kurko avatar Jun 12 '15 00:06 kurko

I think something like this.emberSync.findQuery('post', {id: '27', fetchOnline: false}); would be better because then it complies with ED Store interface.

Also, could you move this code into a PR?

kurko avatar Jun 12 '15 00:06 kurko