meteor/meteor

[3.0] insertAsync on client won't persist local document

bhunjadi opened this issue · 2 comments

Description / reproduction

Please check this failing test: https://github.com/bhunjadi/meteor/blob/795e61aff0c191257937c07eccad7438b2394de4/packages/mongo/allow_tests.js#L1164

Run the test with:

./meteor test-packages mongo

After insertAsync, client doesn't have the document in local collection anymore.

I first observed this when updating meteor-collection-hooks for Meteor 3.0. Here is the failing test.

Notes:

  • Server-side test is working.
  • If you leave out removeAsync, it still fails
  • I'm getting this error in the console: "Method stub (/test_again/insertAsync) took too long and could cause unexpected problems. Learn more at https://github.com/zodern/fix-async-stubs/#limitations"

Debugging:

I noticed that local document exists briefly and it gets deleted.
It seems to me this is because additional event is triggered which removes the document.

What happens is that collection.update method is called with replace msg.
If you look in collection.js the replace value will be undefined, which will trigger the removal of the document couple of lines below.

 if (msg.msg === 'replace') {
  var replace = msg.replace; // will be undefined
  if (!replace) {
    // we'll end up here
    if (doc) self._collection.remove(mongoId);
  } else if (!doc) {
    self._collection.insert(replace);
  } else {
    // XXX check that replace has no $ ops
    self._collection.update(mongoId, replace);
  }
  return;
}

Why it is undefined? Because of this line in minimongo/local_collection.

prepareInsert(doc) {
    ...
    // Here we only set id, but without document. 
    this._saveOriginal(id, undefined);
    this._docs.set(id, doc);

    return id;
  }

I also observed that adding resolverType: 'stub' fixes the test.

const coll = new Mongo.Collection('test_again', {
  resolverType: 'stub'
});

Version
Forked release-3.0 repo

Last version where the problem did not occur
n/a (there was no insertAsync on client)

OS
WSL2 (2.0.14), Ubuntu 22.04.4 LTS
Kernel: 5.15.133.1-microsoft-standard-WSL2

Expected behavior
Document should be in local collection.

Actual behavior
Document is not persisted in local collection.

Thank you for your detailed report.

In Meteor 3.x, a distinction exists between stub and server promises. The former handles client simulation and minimongo population, while the latter solely manages success or error on the server call without populating the data in minimongo. The data is persisted on the server in both.

The resolverType option offers stub and server values.

Yes, resolverType was introduced recently to cover this fix. There is more information about this configuration on this PR, #12969

I would say we could persue this behavior and making it persistant on use server promise, but it has not been an easy task. I would like to test though some of the debugging points you mentioned.

However, the best I can say for now is the usage of resolveType as stub on those scenarios where you care about data present on the client, or rely on methods and subscriptions to read the data back into the client if you decide to use the server approach.

Please, refer to this comment to understand the nature of the new async approach using promises in comparison on how was handled on previous Meteor versions.

In this specific issue you must use resolveType: 'stub' which handle properly the stub behaviors on running collection operations and will keep isomorphic code on your tests.