From e03d35460d752b30f668f5f0e6ffa71cb677ee2f Mon Sep 17 00:00:00 2001 From: Naomi Seyfer Date: Tue, 12 Mar 2013 18:04:41 -0700 Subject: [PATCH] Account for the case where a query might have been stopped before recompute In minimongo, sometimes we precompute a list of queries that need recomputation, and then recompute them. When this happens, we call callbacks that sometimes end up stopping the query, which removes it from the list of queries on the collection. Without checking for this case, it casued an exception. --- packages/livedata/livedata_connection.js | 4 ++- packages/minimongo/minimongo.js | 33 ++++++++++++++---------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/packages/livedata/livedata_connection.js b/packages/livedata/livedata_connection.js index 0c3fb5f773..34f1df7e58 100644 --- a/packages/livedata/livedata_connection.js +++ b/packages/livedata/livedata_connection.js @@ -643,9 +643,11 @@ _.extend(Meteor._LivedataConnection.prototype, { // // Tests can set the 'expected' flag on an exception so it won't // go to log. - if (exception && !exception.expected) + if (exception && !exception.expected) { + debugger; Meteor._debug("Exception while simulating the effect of invoking '" + name + "'", exception, exception.stack); + } } // At this point we're definitely doing an RPC, and we're going to diff --git a/packages/minimongo/minimongo.js b/packages/minimongo/minimongo.js index 638b8a4f3d..260df733d2 100644 --- a/packages/minimongo/minimongo.js +++ b/packages/minimongo/minimongo.js @@ -419,14 +419,15 @@ LocalCollection.prototype.insert = function (doc) { var query = self.queries[qid]; if (query.selector_f(doc)) { if (query.cursor.skip || query.cursor.limit) - queriesToRecompute.push(query); + queriesToRecompute.push(qid); else LocalCollection._insertInResults(query, doc); } } - _.each(queriesToRecompute, function (query) { - LocalCollection._recomputeResults(query); + _.each(queriesToRecompute, function (qid) { + if (self.queries[qid]) + LocalCollection._recomputeResults(self.queries[qid]); }); }; @@ -460,12 +461,12 @@ LocalCollection.prototype.remove = function (selector) { for (var i = 0; i < remove.length; i++) { var removeId = remove[i]; var removeDoc = self.docs[removeId]; - _.each(self.queries, function (query) { + _.each(self.queries, function (query, qid) { if (query.selector_f(removeDoc)) { if (query.cursor.skip || query.cursor.limit) - queriesToRecompute.push(query); + queriesToRecompute.push(qid); else - queryRemove.push([query, removeDoc]); + queryRemove.push({qid: qid, doc: removeDoc}); } }); self._saveOriginal(removeId, removeDoc); @@ -473,11 +474,15 @@ LocalCollection.prototype.remove = function (selector) { } // run live query callbacks _after_ we've removed the documents. - for (var i = 0; i < queryRemove.length; i++) { - LocalCollection._removeFromResults(queryRemove[i][0], queryRemove[i][1]); - } - _.each(queriesToRecompute, function (query) { - LocalCollection._recomputeResults(query); + _.each(queryRemove, function (remove) { + var query = self.queries[remove.qid]; + if (query) + LocalCollection._removeFromResults(query, remove.doc); + }); + _.each(queriesToRecompute, function (qid) { + var query = self.queries[qid]; + if (query) + LocalCollection._recomputeResults(query); }); }; @@ -516,8 +521,10 @@ LocalCollection.prototype.update = function (selector, mod, options) { } _.each(recomputeQids, function (dummy, qid) { - LocalCollection._recomputeResults(self.queries[qid], - qidToOriginalResults[qid]); + var query = self.queries[qid]; + if (query) + LocalCollection._recomputeResults(query, + qidToOriginalResults[qid]); }); };