derbyjs / racer

Realtime model synchronization engine for Node.js
1.18k stars 117 forks source link

query immediately after set gives unexpected empty result #216

Closed enjalot closed 3 months ago

enjalot commented 9 years ago

from a coworker:

I was doing a query immediately after doing a set, and the query wasn't picking up on the changes. It made sense after I was explained what was going on behind the scenes, but it's a subtle gotcha that's not documented anywhere.

model.set('users.42.foo', 'abc');
query = model.query('users', {foo: 'abc'};
model.fetch(query, function(err) {
  console.log(query.get());  // Query results are empty...
  console.log(model.get('users.42.foo'));  // But this will be 'abc'!
});

this is because local operations haven't been flushed. we either want to fix this experience or document it well.

wenzowski commented 9 years ago

While the reasons are sound, it certainly isn't intuitive that model.query() roundtrips but model.at() doesn't need to. Is there currently a way to wait for flush other than passing a callback to model.close()?

Would be really cool if we had minimongo loaded in the browser but that's a nontrivial feature request.

ericyhwang commented 9 years ago

Said coworker here!

The "workaround" for the issue was to either use the optional callback to model.set, which is called when the operation completes:

model.set('users.42.foo', 'abc', function(err) {
  query = model.query('users', {foo: 'abc'});
  model.fetch(query, function(err) {
    console.log(query.get());  // Query will be up-to-date.
  });
});

Or, with multiple edit operations, another thing that seemed to work was using the (currently undocumented) model.whenNothingPending:

model.set('users.42.foo', 'abc');
model.set('users.43.foo', 'abc');
model.whenNothingPending(function(err) {
  query = model.query('users', {foo: 'abc'});
  model.fetch(query, function(err) {
    console.log(query.get());  // Query will be up-to-date.
  });
});

Being able to do queries in the client would be really neat, but then your query results would depend on what documents you have loaded in the client. For instance, there could be lots of user documents with {foo: 'abc'} that you don't have locally, so the query results on your local data versus the remote data would be different.

wenzowski commented 9 years ago

Both options very useful, thanks @ericyhwang.

Yes, you'd still want remote queries to roundtrip but the very fact that if you didn't fetch/subscribe a query it would only return documents that exists locally would be very useful in many cases. I have what are effectively join collections coupled with reactive model functions to work around the fact that we only have remote queries right now.

If we were to entertain the large feature request of local queries, I would hope that a subscribed query would be immediately run as a local query and be subsequently replaced with its remote counterpart post-roundtrip.