Reputation: 2820
I am encountering a problem with subscribing/publishing in Meteor. I've written an example Meteor app to help narrow the scope of the problem.
I am publishing a collection on the server that is filtered by a parameter passed in through a subscription on the client. This subscription is within an autosubscribe, which leverages a session variable to reactively update the subscriptions.
When changing the state of this particular session variable, the collection on the client isn't getting updated properly, or at least that's what I gather. I've spent the whole day on this and have not found an issue in code I control. I suspect I'm either not understanding how to setup proper pub-sub in Meteor, or there's a problem within Meteor.
To reproduce the problem, start a new Meteor project and use the following (Make sure to remove the autopublish package when trying it out):
HTML (test.html for example):
<head>
<title>pubsubbug</title>
</head>
<body>
{{> main}}
</body>
<template name="main">
<h1>Example showing possible bug in Meteor wrt pub-sub</h1>
<p><button name="showall">show all ({{showall}})</button></p>
<div style="float:left;width:400px;">
<h2>Notes:</h2>
<ul>
{{#each notes}}
<li>{{title}}</li>
{{/each}}
</ul>
</div>
<div style="float:left;">
<h2>Notes (copied):</h2>
<ul>
{{#each notes_copied}}
<li>{{title}}</li>
{{/each}}
</ul>
</div>
</template>
JS (test.js for example)
if (Meteor.is_client) {
Notes = new Meteor.Collection("notes_collection");
NotesCopied = new Meteor.Collection("notes_collection_copied");
Session.set("showall", false);
Meteor.autosubscribe(function () {
Meteor.subscribe("notes_subscription", Session.get("showall"), function () {
console.log("Notes count:", Notes.find().count());
});
Meteor.subscribe("notes_subscription_copied", Session.get("showall"), function () {
console.log("Bug? This isn't getting called.");
console.log("NotesCopied count:", NotesCopied.find().count());
});
});
Template.main.notes = function () {
return Notes.find();
};
Template.main.notes_copied = function () {
return NotesCopied.find();
};
Template.main.showall = function () {
return Session.get("showall");
};
Template.main.events = {
"click button[name='showall']": function (evt) {
Session.set("showall", !Session.get("showall"));
}
};
}
if (Meteor.is_server) {
Notes = new Meteor.Collection("notes_collection");
var getNotes = function (showall) {
if (showall) {
return Notes.find({}, {sort: {title: 1}});
} else {
return Notes.find({visible: true}, {sort: {title: 1}});
}
};
Meteor.publish("notes_subscription", function (showall) {
// By sending the Notes back with the same uuid as before, the
// client end seems to get confused:
return getNotes(showall);
});
Meteor.publish("notes_subscription_copied", function (showall) {
var notes = getNotes(showall);
var self = this;
// Copy notes into a new notes collection (see NotesCopied on client).
// By generating a new uuid, we don't get an issue with the notes
// on the client getting screwed up:
notes.forEach(function (note) {
var uuid = Meteor.uuid(); // note._id will cause same problem
self.set("notes_collection_copied", uuid, {title: note.title});
});
self.flush();
self.complete();
});
// Add example notes
Meteor.startup(function () {
if (Notes.find().count() === 0) {
Notes.insert({title: "Note #1 (always visible)", visible: true});
Notes.insert({title: "Note #2 (always visible)", visible: true});
Notes.insert({title: "Note #3 (always visible)", visible: true});
Notes.insert({title: "Note #4 (only visible when showall true)", visible: false});
Notes.insert({title: "Note #5 (only visible when showall true)", visible: false});
Notes.insert({title: "Note #6 (only visible when showall true)", visible: false});
}
});
}
An explanation of what you will be seeing:
There will be a button that, when clicked, simply toggles a session variable (showall) between true and false.
Two subscriptions exist (within an autosubscribe), one that exemplifies the bug, and another that is suffixed with _copied
, which is a test to demonstrate that when the collection in question is "copied" and new uuid's are assigned, the results are displayed properly. I couldn't figure out what to do with this particular bit of info... I don't want new uuid's.
So basically, when the show all button is clicked repeatedly, the first column Notes: will display incorrect results, and after a few clicks won't show anything.
On the other hand, the second column Notes (copied):, whose uuid's are re-generated each time, shows up correctly.
Is this a bug? Or is there a proper way to do this?
EDIT: Example above live over at http://pubsubbug.meteor.com/
Upvotes: 1
Views: 691
Reputation: 12348
Not experiencing your bug on the developer branch on Windows. Since this is the case, it is a good sign that there is nothing wrong with your code. It appears that you see something buggy regarding the subscriptions and/or how Mongo queries.
Meteor itself is most likely running the stable (= master) release on their hosting, so you will have to try a different approach or wait for a new release. Unless you can support running on devel...
Upvotes: 2