I am seeing unexpected behavior in a basic meteor application that leads to a design pattern question I'd like to pose for comment.
The meteor app has a server that reads a list of graph nodes and edges from an external source, inserts the nodes to a Nodes collection, inserts the edges to an Edges collection, and then inserts a special document into a third Signal collection. The client has "added:" observers on all three collections to detect changes.
I expected that all the nodes and links would be seen on the client before the signal command to draw. Instead I'm seeing about 1/3 of the nodes and edges being added AFTER the signal command on the client.
I would like to avoid drawing the graph until after all the data is there, hence the use of the Signal collection. Is there a better way to do this in Meteor? Is there a different design pattern I should be using? Seems like this should be a common question.
// server side inserts
_.each(model.nodes, function(r) {
Nodes.insert({ name: r.name });
});
_.each(model.edges, function(r) {
Edges.insert({ source: r.src, target: r.tgt, value: r.value });
});
Signal.remove({});
Signal.insert({command: "draw-graph"});
// client side observer
Template.template_mission_impact.rendered = function () {
var graph = new myGraph(...);
Nodes.find().observe({
added: function (doc) {
graph.addNode(doc._id, doc.name);
}
});
Edges.find().observe({
added: function (doc) {
graph.addEdge(doc._id, doc.source, doc.target, doc.value);
}
});
Signal.find().observe({
added: function (doc) {
if (doc.command === "draw-graph") {
graph.draw();
}
}
});
};
The schema looks fine, just use template subscriptions and wrap your template in a #subscriptionsReady helper. In doing so, the rendered callback won't run until all the docs are there.
In general, graph networks get really big really fast and after about 10000 docs subscriptions will get noticeably slower. If you're data doesn't need reactivity, eliminating it (publishing a fetch, not observing) can give you a serious speed boost.