Add cursorSupportedByOplogTailing.

This commit is contained in:
David Glasser
2013-08-14 13:36:44 -07:00
parent 4ea191e452
commit 4d2097912d
3 changed files with 74 additions and 0 deletions

View File

@@ -1264,9 +1264,48 @@ MongoConnection.prototype._observeChangesTailable = function (
};
};
// Does our oplog tailing code support this cursor? For now, we are being very
// conservative and allowing only simple queries with simple options.
var cursorSupportedByOplogTailing = function (cursorDescription) {
// First, check the options.
var options = cursorDescription.options;
// We don't yet implement field filtering for oplog tailing (just because it's
// not implemented, not because there's a deep problem with implementing it).
if (options.fields) return false;
// This option (which are mostly used for sorted cursors) require us to figure
// out where a given document fits in an order to know if it's included or
// not, and we don't track that information when doing oplog tailing.
if (options.limit || options.skip) return false;
// For now, we're just dealing with equality queries: no $operators, regexps,
// or $and/$or/$where/etc clauses. We can expand the scope of what we're
// comfortable processing later.
return _.all(cursorDescription.selector, function (value, field) {
// No logical operators like $and.
if (field.substr(0, 1) === '$')
return false;
// We only allow scalars, not sub-documents or $operators or RegExp.
// XXX Date would be easy too, though I doubt anyone is doing equality
// lookups on dates
return typeof value === "string" ||
typeof value === "number" ||
typeof value === "boolean" ||
value === null ||
value instanceof Meteor.Collection.ObjectID;
});
};
// XXX We probably need to find a better way to expose this. Right now
// it's only used by tests, but in fact you need it in normal
// operation to interact with capped collections (eg, Galaxy uses it).
MongoInternals.MongoTimestamp = MongoDB.Timestamp;
MongoInternals.Connection = MongoConnection;
MongoTest = {
cursorSupportedByOplogTailing: cursorSupportedByOplogTailing
};

View File

@@ -0,0 +1,32 @@
var OplogCollection = new Meteor.Collection("oplog-" + Random.id());
Tinytest.add("mongo-livedata - oplog - cursorSupportedByOplogTailing", function (test) {
var supported = function (expected, selector) {
var cursor = OplogCollection.find(selector);
test.equal(
MongoTest.cursorSupportedByOplogTailing(cursor._cursorDescription),
expected);
};
supported(true, "asdf");
supported(true, 1234);
supported(true, new Meteor.Collection.ObjectID());
supported(true, {_id: "asdf"});
supported(true, {_id: 1234});
supported(true, {_id: new Meteor.Collection.ObjectID()});
supported(true, {foo: "asdf",
bar: 1234,
baz: new Meteor.Collection.ObjectID(),
eeney: true,
miney: false,
moe: null});
supported(true, {});
supported(false, {$and: [{foo: "asdf"}, {bar: "baz"}]});
supported(false, {foo: {x: 1}});
supported(false, {foo: {$gt: 1}});
supported(false, {foo: [1, 2, 3]});
});

View File

@@ -35,6 +35,8 @@ Package.on_use(function (api) {
// Stuff that should be exposed via a real API, but we haven't yet.
api.export('MongoInternals', 'server');
// For tests only.
api.export('MongoTest', 'server');
api.add_files('mongo_driver.js', 'server');
api.add_files('local_collection_driver.js', ['client', 'server']);
@@ -53,4 +55,5 @@ Package.on_test(function (api) {
api.add_files('allow_tests.js', ['client', 'server']);
api.add_files('collection_tests.js', ['client', 'server']);
api.add_files('observe_changes_tests.js', ['client', 'server']);
api.add_files('oplog_tests.js', 'server');
});