DDP Protocol for sending collection updates from the client side?

395 views
Skip to first unread message

Ken Yee

unread,
Jul 2, 2013, 10:14:06 PM7/2/13
to meteo...@googlegroups.com
This document doesn't seem to document how collections get updated from the client:
  https://github.com/meteor/meteor/blob/master/packages/livedata/DDP.md

I looked through most of the livedata package and it's not obvious how this is done.  Are the added/updated messages bidirectional?  The document says they're only server->client....


Avital Oliver

unread,
Jul 8, 2013, 2:49:41 PM7/8/13
to meteo...@googlegroups.com
There are hardcoded methods named /COLLECTION-NAME/{insert,update,remove}. You can see this by loading a Meteor app in Chrome and looking at the websocket frames in the developer console. They are defined in Meteor.Collection.prototype._defineMutationMethods.





--
You received this message because you are subscribed to the Google Groups "meteor-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to meteor-talk...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Ken Yee

unread,
Jul 8, 2013, 5:25:37 PM7/8/13
to meteo...@googlegroups.com


On Monday, July 8, 2013 2:49:41 PM UTC-4, Avital Oliver wrote:
There are hardcoded methods named /COLLECTION-NAME/{insert,update,remove}. You can see this by loading a Meteor app in Chrome and looking at the websocket frames in the developer console. They are defined in Meteor.Collection.prototype._defineMutationMethods.

Thanks Avital.
For the first parameter, I had to pass in the _id prefix.  Even though the code at https://github.com/meteor/meteor/blob/master/packages/mongo-livedata/collection.js said I could pass in a scalar and it looks like it should handle it:
  // shorthand -- scalars match _id
  if (LocalCollection._selectorIsId(selector))
    selector = {_id: selector};

It caused an ugly error on the server:
xception while invoking method '/TestCollection/update' Error: selector must be a valid JavaScript object
    at Object.Future.wait (/home/kenyee/.meteor/tools/cc18dfef9e/lib/node_modules/fibers/future.js:319:16)
    at _Mongo.update (app/packages/mongo-livedata/mongo_driver.js:269:12)
    at Meteor.Collection._defineMutationMethods._.each.m.(anonymous function) (app/packages/mongo-livedata/collection.js:545:38)
    at maybeAuditArgumentChecks (app/packages/livedata/livedata_server.js:1367:12)


This is what the websockets call looks like now :-)

Sending {"id":"5","method":"/TestCollection/update","params":[{"_id":"AwuxsXsxoGK3SvdA2"},{"$set":{"testfield":"hello"}}],"msg":"method"}
Received response: {"msg":"result","id":"5"}
Received response: {"msg":"changed","collection":"TestCollection","id":"AwuxsXsxoGK3SvdA2","fields":{"testfield":"hello"}}
Received response: {"msg":"updated","methods":["5"]}

p.s., I found that I needed the result msg to be received last for method calls, even though the docs say you can get updated/result events in any order after a method call.  The reason is in Java, we have to track the listeners/callbacks you attach to method calls and remove them after the method is "done" or you'll end up allocating an object that is never garbage collected.  I'm doing this in the "result" msg since it doesn't matter if I get the updated message for now.

Ken Yee

unread,
Jul 8, 2013, 6:11:31 PM7/8/13
to meteo...@googlegroups.com


On Monday, July 8, 2013 2:49:41 PM UTC-4, Avital Oliver wrote:
There are hardcoded methods named /COLLECTION-NAME/{insert,update,remove}. You can see this by loading a Meteor app in Chrome and looking at the websocket frames in the developer console. They are defined in Meteor.Collection.prototype._defineMutationMethods.

One other thing that was weird:
I subscribed to the collection.
Then I did an insert but never got an added message (verified w/ mongodb that the doc made it in)
Then did an update which resulted in a changed message coming back.
Then did a remove which resulted in a removed message coming back.

Is it a bug that the insert doesn't cause an add message or is the lack of an error response enough of an indicator?

Avital Oliver

unread,
Jul 8, 2013, 11:51:37 PM7/8/13
to meteo...@googlegroups.com
I did a small test and definitely did get an added message after inserting a document.

I deployed a test app to http://tmp-test-todos.meteor.com and added a task. Then I looked at the network tab in the Chrome developer console and inspected the websocket connection. I saw:

["{\"msg\":\"method\",\"method\":\"/todos/insert\",\"params\":[{\"text\":\"new\",\"list_id\":\"fQi9uTE6ht7piC6j5\",\"done\":false,\"timestamp\":1373341727913,\"tags\":[],\"_id\":\"chyPGEfyzSCLqR8rQ\"}],\"id\":\"1\"}"]

a["{\"msg\":\"result\",\"id\":\"1\"}"]

a["{\"msg\":\"added\",\"collection\":\"todos\",\"id\":\"chyPGEfyzSCLqR8rQ\",\"fields\":{\"text\":\"new\",\"list_id\":\"fQi9uTE6ht7piC6j5\",\"done\":false,\"timestamp\":1373341727913,\"tags\":[]}}"]

a["{\"msg\":\"updated\",\"methods\":[\"1\"]}"]

Ken Yee

unread,
Jul 9, 2013, 3:13:26 PM7/9/13
to meteo...@googlegroups.com


On Monday, July 8, 2013 11:51:37 PM UTC-4, Avital Oliver wrote:
I did a small test and definitely did get an added message after inserting a document.

Sorry Avital.  I beeeee idiottttt.  I forgot the subscription filters based on userid and didn't send that up when I did the insert :-P

Works well now:
Sending {"support":["pre1"],"msg":"connect","version":"pre1"}
Received response: {"msg":"connected","session":"cPeZk7FyyG95TGdTp"}
Sending {"id":"1","method":"login","params":[{"password":"password","user":{"email":"te...@test.com"}}],"msg":"method"}
Received response: {"msg":"added","collection":"users","id":"qMEnmjwxkgxrw4xcp","fields":{"emails":[{"address":"te...@test.com","verified":false}]}}
Received response: {"msg":"updated","methods":["1"]}
Received response: {"msg":"result","id":"1","result":{"token":"d8q5Q3begPz8aZi7a","id":"qMEnmjwxkgxrw4xcp"}}
Sending {"id":"2","method":"clearCollection","params":[],"msg":"method"}
Sending {"id":"3","name":"testData","params":[],"msg":"sub"}
Received response: {"msg":"updated","methods":["2"]}
Received response: {"msg":"result","id":"2","result":true}
Received response: {"msg":"ready","subs":["3"]}
Sending {"id":"4","method":"/TestCollection/insert","params":[{"testfield":"test","docnum":1,"_id":"a5cec637-e855-46cd-9725-01242764e543","userid":"qMEnmjwxkgxrw4xcp","value":"a"}],"msg":"method"}
Received response: {"msg":"result","id":"4"}
Received response: {"msg":"added","collection":"TestCollection","id":"a5cec637-e855-46cd-9725-01242764e543","fields":{"testfield":"test","docnum":1,"userid":"qMEnmjwxkgxrw4xcp","value":"a"}}
Received response: {"msg":"updated","methods":["4"]}
Sending {"id":"5","method":"/TestCollection/update","params":[{"_id":"a5cec637-e855-46cd-9725-01242764e543"},{"$set":{"testfield":"hello"}}],"msg":"method"}

Received response: {"msg":"result","id":"5"}
Received response: {"msg":"changed","collection":"TestCollection","id":"a5cec637-e855-46cd-9725-01242764e543","fields":{"testfield":"hello"}}

Received response: {"msg":"updated","methods":["5"]}
Sending {"id":"6","method":"/TestCollection/remove","params":[{"_id":"a5cec637-e855-46cd-9725-01242764e543"}],"msg":"method"}
Received response: {"msg":"result","id":"6"}
Received response: {"msg":"removed","collection":"TestCollection","id":"a5cec637-e855-46cd-9725-01242764e543"}
Received response: {"msg":"updated","methods":["6"]}

The library is in a good enough state (not quite as well done as the ObjectiveDDP library but getting there) to try writing a native Android app for the Parties example now...will post again when that's working :-)

Reply all
Reply to author
Forward
0 new messages