Meteor Methods: How do methods that create or update records resolve changes?


#1

Meteor methods have built-in magic where inserting a record creates a version on the client AND resolves the ID against the version created by the server version of this method. This allows for a seamless latency-compensation “optimistic UI” experience.

Unfortunately for me I’ve been trying to do some advanced collection/subscription work which has broken this magic. I will describe my situation below but for now I’m mostly curious - does anyone know how this “change resolution” meteor method magic works? I’m hoping with some insight I can make the magic work again on my strange situation.

So, simply put: when a method inserts a record how does meteor resolve the inserted ID between the simulation record inserted into minimongo and the real record which results from the server version of the method and is sent to the client over the subscription? Can anyone point me to meteor code where this happens or doc where it is described?

The most closest piece of doc text I’ve found about this is:

Meteor tracks the database writes performed by methods, both on the client and the server, and does not invoke asyncCallback until all of the server’s writes replace the stub’s writes in the local cache. In some cases, there can be a lag between the method’s return value being available and the writes being visible: for example, if another method still outstanding wrote to the same document, the local cache may not be up to date until the other method finishes as well. If you want to process the method’s result as soon as it arrives from the server, even if the method’s writes are not available yet, you can specify an onResultReceived callback to Meteor.apply.

This is unfortunately just a description that Meteor does do this, but not about how or where.

I’ll try to create a minimally reproducible example - but for the mean time I’ll simply explain it: I (we) have a collection on the server with records. On the client I want to bring in records from this collection by two channels: search and/or subscription. To do this on the client I create three collections: one populated with search results, one which has a subscription to the server collection, and finally one that is user facing that has changes in the “search” and “sub” changes propagated into it. Changes to this collection (that are not from the “sub”) are propagated back to the “sub” collection so they persist.


#2

AFAIK, Meteor just creates the id on the client and sends it to the server. There is no “resolution” here.


#3

I believe you are right in the case that you directly execute SomeCollection.insert({}) on the client (which on the server executes Meteor.server.method_handlers['/some_collections/insert']()). I don’t believe this to be the case inside a meteor method though… which could be doing as many inserts as it wants or could have any manner of different behavior happen in simulation vs. server.


#4

I think one of the keys here is the randomSeed parameter in the DDP message. In my plain collections it is being sent with the method request, in my merged collections it is not. If anyone knows about how DDP decides to include a randomSeed that would be useful.


#5

I would start here, it was not much work to find