Giter VIP home page Giter VIP logo

Comments (16)

nilbus avatar nilbus commented on June 17, 2024

Thanks for reporting this. I won't be able to look in to it immediately, but you may be right. Feel free to look into a fix for it.

from backbone.dualstorage.

t3living avatar t3living commented on June 17, 2024

The error occurred again, and I have more information. The issue IS NOT that the application went offline. I don't know the full cause of the error but here is the console log dump which shows the sequence of events.
create an entity with picks.create(data,{wait:true, async:false} ) - ok
update the same model using this.model.save({updated attribs}) - ok
update again using this.model.save({updated attribs}) - error
The error was a Ajax 404 - page not found
upon closer inspection the url that was used was incorrect.
The url that was attempted was api/pickdrops/query/sql
but the base model and collection url is simply api/pickdrops.

The api/pickdrops/query/sql is an api that I use in the app prior to this execution sequence, but I use it by overriding the url parameter in a fetch(url: 'api/pickdrops/query/sql', ...)

The issue seems to be that for some reason this url is still referenced.

from backbone.dualstorage.

t3living avatar t3living commented on June 17, 2024

After looking into these issues further I discovered three issues and have a work around for all of them at the moment.

  1. Since my pagination API required a different URL than my basic collection, I was supplying a URL parameter when fetching some of the models. It turns out that when you fetch and supply a url, that is the url assigned to the models. So when these paginated models were changed then syncDirtyAndDestroyed attempted to PUT to the paginated URL instead of the collection's base definition. ==> my solution was to change my pagination API so that the base URLs were the same.
  2. I believe there is a timing / async issue with performing two syncDirtyAndDestroyed operations close together. The error "Cannot call method 'save' of undefined backbone.dualstorage.js:25" occurs on the second call because when syncDirtyAndDestroyed attempts to model.save the model identified on the _dirty list, the model is already removed. I think the error arises because of a sequence such as
    sync#1-initiated
    sync#1-reads _dirty id's, finds the associated model and launches an async save, it removes the dirty:true param, but does not remove the _dirty id from the list until success.
    Meanwhile sync#2 initiates, finds _dirty list, but when it goes to execute model.save the model does not exist because the dirty:true param was cleaned for the save operation.
    ==> I put in a work around to check the collection for dirty models.
  3. My third issue occurred when I created and saved models for a remote-only collection, but I never saved them into a local collection because I have no need for a local collection. When offline, the models were correctly given a local id and listed on the _dirty list, but when syncDirtyAndDestroyed attempted to issue model.save, there was no model because it was looking in the collection. ==> my solution was to save my models into a local collection.

from backbone.dualstorage.

nilbus avatar nilbus commented on June 17, 2024

Good investigation work.

  1. That is some interesting behavior with fetch({url: ...}) that you're seeing. It does pass the same options you send to fetch along to every other method it calls that takes options: reset -> add -> set -> _prepareModel -> new Model, but it doesn't seem that passing a url option when creating a new model would actually override the url attribute you set in your code. What does happen however is the fetched models' collection attribute will be set to the collection you used to fetch them. Since the model's url method delegates to the collection's urlRoot || url, that's probably why you're seeing the URL difference. It might be worth thinking about which collection they should actually belong to after being fetched, and assign it to the other if needed.

  2. You're correct; there is a synchronicity issue here. This is the same underlying cause as issue #35. I attempted to solve that there, but our first implementation had problems. We must be sure to keep this in mind as we implement another fix for that issue. A short term fix would be to check to ensure a model was found:

       for id in ids
         model = if id.length == 36 then @where(id: id)[0] else @get(id)
    -    model.save()
    +    model?.save()
    

    I'll go ahead and make this change as a temporary measure until we work out the synchronicity issues with syncDirtyAndDestroyed.

  3. Syncing a collection with remote: true should definitely not be marking the models dirty. It should behave instead as if backbone.dualStorage was not even there. How did you mark the collection remote? Could this be related to having the wrong collection assigned to the model, as discussed in the 1st point?

from backbone.dualstorage.

t3living avatar t3living commented on June 17, 2024
  1. all the models are part of the same collection, the only difference is how they were fetched. when I create individual models on the client I add them directly to the collection and sync simply uses the url || urlRoot. But some previously created models find their way into the local collection via a pagination api which uses a parameterized version of the url.
  2. The issue was not about syncing a collection with remote:true, but rather syncing a model with remote:true. Before my fix, I had a collection defined but have no need to populate it in the client so I was just creating models and firing them to the server api with model.save().

from backbone.dualstorage.

t3living avatar t3living commented on June 17, 2024

At the moment I am having difficulty with the collection.create({local:true}) and model.save({local:true}) commands. the models are saved local, but also set to the server. I must have missed something in a recent change because I am not familiar with the dualsync:true command in the latest releases

from backbone.dualstorage.

nilbus avatar nilbus commented on June 17, 2024

I updated the master branch and reverted the commit that was causing this issue. Could you try that out?

from backbone.dualstorage.

nilbus avatar nilbus commented on June 17, 2024
  1. I'm still not quite sure how your model url got changed, since backbone doesn't do this, at least in the obvious case:

    m = new (Backbone.Model.extend({url: 'http://originalURL'}));
    => child {cid: "c185", attributes: Object, _changing: false, _previousAttributes: Object, changed: Object…}
    m.fetch({url: 'http://custom'});
    => undefined
    m.url
    => "http://originalURL"
    
  2. Let's see if I understand what's going on. You're saving these models, which don't have a collection set on them. The collection and model share a URL scheme, so localSync stores these models as if they are part of the collection. When the model fails to save, it is added to the dirty set. When you tell your collection to syncDirtyAndDestroyed, it tries to find those dirty models in the collection and save them, but it can't find them in your collection. Sound about right? If you want your collection to sync those models, you need to put those models in your collection. If not, this new change (cd17ff2) should do exactly what you want, ignore them.

from backbone.dualstorage.

t3living avatar t3living commented on June 17, 2024

off grid for a bit...get back soon

from backbone.dualstorage.

t3living avatar t3living commented on June 17, 2024

I tried to revert my code to recreate the error, but there have been too many changes and I can't seem to recreate the error.

from backbone.dualstorage.

nilbus avatar nilbus commented on June 17, 2024

Okay. I'll close this for now, but please let me know if you are able to reproduce any of these. Thanks!

from backbone.dualstorage.

t3living avatar t3living commented on June 17, 2024

bumped into the issue again in the following scenario

  1. define model & collection with a standard url
  2. fetch with a custom url
  3. the collection retains the url assigned in the definition, but the fetched model has the custom url.

here is the javascript followed by console dump javascript

PickDrop = Backbone.Model.extend({urlRoot: 'api/pickdrops'});
PickDrops = Backbone.Collection.extend({model: PickDrop, url:"api/pickdrops"});
var pds = new PickDrops({local:false});
console.log("before custom url fetch url= "+pds.url);
pds.fetch({url:'api/pickdrops/query/sql',
           async:false,
           data:{qry:' pickdate >= 1381381200000 AND pickdate <= 1382331540000 AND contractid = 4'}});
console.log("the pds = ",pds);
console.log("after fetch collection url= "+pds.url);
var amodel = pds.shift();
console.log("the model= ",amodel);
console.log("the models url = "+amodel.url);

Console output:

before custom url fetch url= api/pickdrops

the pds = r {length: 10, models: Array[10], _byId: Object, constructor: function, model: function…}
      _byId: Object
      length: 9
      models: Array[9]
          __proto__: s

after fetch, collection url= api/pickdrops url-error.html:36

the model=  r {cid: "c2", attributes: Object, url: "api/pickdrops/query/sql", _changing: false, _previousAttributes: Object…}
    _changing: false
    _events: Object
    _pending: false
    _previousAttributes: Object
    attributes: Object
    changed: Object
    cid: "c2"
    id: "67"
    url: "api/pickdrops/query/sql"
    __proto__: s

the model's url= api/pickdrops/query/sql

from backbone.dualstorage.

nilbus avatar nilbus commented on June 17, 2024

I am able to reproduce what you're seeing with Backbone 1.0.0, but not in 1.1.0:

...
the models url = function () {
      var base = _.result(this, 'urlRoot') || _.result(this.collection, 'url') || urlError();
      if (this.isNew()) return base;
      return base + (base.charAt(base.length - 1) === '/' ? '' : '/') + encodeURIComponent(this.id);
    }

Notably, url property no longer gets set on the model as an attribute when you pass url as an option to fetch. I'll close this ticket since it seems to be a change in Backbone. Are you able to update to 1.1.0?

from backbone.dualstorage.

nilbus avatar nilbus commented on June 17, 2024

It seems the change was added late to the changelog and doesn't appear on backbonejs.org yet, but there has been a PR merged to fix that:

jashkenas/backbone#2864

Backbone Models no longer automatically attach the <tt>url</tt> and <tt>urlRoot</tt>
options passed to the constructor.

from backbone.dualstorage.

t3living avatar t3living commented on June 17, 2024

I will investigate BB 1.1.0...in any case it doesn't seem to be a dualStorage specific issue.

from backbone.dualstorage.

t3living avatar t3living commented on June 17, 2024

yep, BB 1.1.0 works fine with a couple of minor adjustments.

from backbone.dualstorage.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.