Skip to content
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

Sync issue when tampering with local collections in MiniMongo #568

Closed
arggh opened this issue Dec 19, 2016 · 8 comments
Closed

Sync issue when tampering with local collections in MiniMongo #568

arggh opened this issue Dec 19, 2016 · 8 comments
Assignees

Comments

@arggh
Copy link
Contributor

arggh commented Dec 19, 2016

Sometimes a developer might wish to update the local MiniMongo collection, for example with a high frequency user interaction such as dragging and updating coordinates.

Documents._collection.update(id, { $set: { coordinate ...

and then, once this high frequency user interaction is complete, update the final value to database.

At this point, calling document.save() does nothing, and I presume it is because Astronomy thinks the value hasn't changed?

What about providing an option to "force" the update, like doc.save({ force: true })?

@lukejagodzinski
Copy link
Member

For now the best way of doing it is reloading a document doc.reload() and later saving doc.save(). I may add the force option in some of the future releases.

@arggh
Copy link
Contributor Author

arggh commented Sep 23, 2017

Bumped into this issue again: Calling doc.reload() doesn't seem to solve the issue: the update doesn't hit the database.

This would be awesome:

onChange: (value) => {
    Docs._collection.update({
       _id: docId
    }, {
       $set: {
         distance: value // on last call to onChange, value is 0
       }
    }); 
},
onEnd: (value) => {
    doc.distance = value; // value is still 0
    doc.save({ fields: ['distance'], forceUpdate: true }); // value gets updated due to forceUpdate-flag
}

@lukejagodzinski
Copy link
Member

Can you make reproduction repository because I don't quite understand your problem

@arggh
Copy link
Contributor Author

arggh commented Sep 24, 2017

Sure, I'll provide a repro, but just in case, here's a more thorough explanation:

Imagine my app has a slider component.

Slider can have values between 0 ... 100. Whatever value it's set at will be saved to a document on database, but I also want to reflect the change in real time on the page. That's what the onChange callback is for.

While the slider is being slided, to prevent my DB from being bombarded with calls, I'm actually updating the local collection: Docs._collection.update(.. , $set: { distance: value } ..

After the slider is released, onEnd callback gets called, and that's when I know I can actually save the value to database: doc.distance = value; doc.save();

The problem is, Astronomy thinks it doesn't need to update the value to database, because I tampered with the local collection on client (new value is same as old value, or so Astronomy thinks!).

So, to overcome this...

I now have to do something like this:

onEnd: (value) => {
    const WHATEVER_MADEUP_VALUE_THAT_IT_CANNOT_ACTUALLY_BE = -1;
    Docs._collection.update({
      _id: doc._id
    }, {
      $set: {
         distance: WHATEVER_MADEUP_VALUE_THAT_IT_CANNOT_ACTUALLY_BE
      }
    });
    doc.distance = value;
    doc.save({ fields: ['distance'] });
}

@lukejagodzinski
Copy link
Member

lukejagodzinski commented Sep 26, 2017

Ok, now I see what is the problem. You're not doing it correctly. First, you shouldn't modify private _collection property as it will not only mess with Astronomy but Meteor too. What you're trying to do is only modify the local state of the component and only propagate changes to the server when you stop moving the slider. If you would do that in let's say React, then you would use a state for that. In Blaze, you can do it using ReactiveVar or other reactive data source. You can also use local collections to only reflect changes locally. When you're finished, then you can update the actual collection. It's not recommended to mess with a collection as it is only local.

@arggh
Copy link
Contributor Author

arggh commented Sep 26, 2017

I do acknowledge there are many ways to implement the scenario explained above with Meteor, some more correct than others :)

I'm using a local collection myself in the case I described since Astronomy doesn't have the forceUpdate-flag, but I thought having that said flag might prove to be useful, not just in this specific scenario!

For example, I can never be 100% sure my collection on client is up to date, but sometimes I want to make sure a change is persisted to DB.

@lukejagodzinski
Copy link
Member

Yep, such a feature might be handy in some scenarios. Maybe I will implement it next week if I have time for that :)

@lukejagodzinski
Copy link
Member

Fixed it in version 2.5.2. Now you can write doc.save({ forceUpdate: true }) when updating a document.

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

No branches or pull requests

2 participants