Latency compensation/ shows duplicates for a second or so


#1

I have a Meteor method in the “collections” folder that inserts something into a collection.
The inserted document shows up twice for a second or so and then disappears. Eg if I insert “Bob” then “Bob Bob” shows up for about a second and then show “Bob”.

I am calling some other methods in my Method. Not sure if this is the issue?


#2

Sounds to me as though your client code is inserting a duplicate somehow, then the server is sending it’s updated data and removing it again. Code in a Gist?


#3

thanks… here’s a simplified version I tweaked https://gist.github.com/adamgins/e9cd0504e1a12cd83073


#4

Your code looks clean. How is the addComment function being called? Do you have an events map?


#5

This is just a guess, but try putting lines 22 through 30 in the callback of Comments.insert() and see if that helps.


#6

@awatson1978 that worked, thanks. Any idea why?
@jchristman I was just doing a Meteor.call('addComment',... re “events map” sorry not 100% sure what you mean?


#7

Um, well, the latency compensation simulates the insertion of the record into the local collection, and then removes it when the server responds with an authenticated record insertion. Your Meteor.calls() were blocking the client-side addComment from resolving, so the latency compensation wasn’t happening when the Comments.insert() resolved; rather, it was resolving after the Meteor.call() were resolved. The callback decoupled things by making the response asynchronous, thereby letting Comments.insert() resolved at the correct time, letting addComment closed up without block, and the template could patch things up correctly as the results came in. It, um… yeah, you had some blocking calls in there.


#8

Put another way:

Meteor.call() is always going to be expensive, because it has to access the network.

Collection.insert(), Collection.update(), etc are going to be both expensive and inexpensive, due to latency compensation, because it’s getting run on both client and server. It has to access the network to get to the server, so that call is expensive; but can access locally for the client which is inexpensive.

In this case, the first “Bob” came from the inexpensive Collection.insert(), the second “Bob” came from the expensive Collection.insert(), the first “Bob” was blocked from being removed because the expensive Meteor.call() hadn’t resolved yet, and when it did finally resolve, latency compensation was able to finally remove the first “Bob”.

Putting the Meteor.call() in the callback allowed the following to happen: the first “Bob” came from the inexpensive “Collection.insert()”, the second “Bob” came from the expensive Collection.insert(), when it arrives it replaces the first “Bob”, patches up the template, and then kicks off the “Meteor.call()” .


#9

Great explanation @awatson1978 thanks heaps :smile:


#10

Are you working on libuv @Siyfion


#11

If you don’t want to wait for a callback and assume an implicit insert success, you can create an id on the client (using the random package) and use that within your insert object. That way, catching up of server responses will not make a difference on the data, given that server respons with success.


#12

No, I’m not, I just shameless stole their icon… Because it’s a FRICKIN’ UNICORN-DINOSAUR.