diff --git a/README.md b/README.md index 8cbbfecf0..adee7b51e 100644 --- a/README.md +++ b/README.md @@ -467,6 +467,7 @@ Additional fields may be added to the error object for debugging context dependi * 4022 - Database adapter does not support queries * 4023 - Cannot project snapshots of this type * 4024 - Invalid version +* 4025 - Passing options to subscribe has not been implemented ### 5000 - Internal error diff --git a/lib/backend.js b/lib/backend.js index 442da075c..96d086479 100644 --- a/lib/backend.js +++ b/lib/backend.js @@ -313,7 +313,11 @@ Backend.prototype._getSnapshotsFromMap = function(ids, snapshotMap) { // Non inclusive - gets ops from [from, to). Ie, all relevant ops. If to is // not defined (null or undefined) then it returns all ops. -Backend.prototype.getOps = function(agent, index, id, from, to, callback) { +Backend.prototype.getOps = function(agent, index, id, from, to, options, callback) { + if (typeof options === 'function') { + callback = options; + options = null; + } var start = Date.now(); var projection = this.projections[index]; var collection = (projection) ? projection.target : index; @@ -326,7 +330,8 @@ Backend.prototype.getOps = function(agent, index, id, from, to, callback) { from: from, to: to }; - backend.db.getOps(collection, id, from, to, null, function(err, ops) { + var opsOptions = options && options.opsOptions; + backend.db.getOps(collection, id, from, to, opsOptions, function(err, ops) { if (err) return callback(err); backend._sanitizeOps(agent, projection, collection, id, ops, function(err) { if (err) return callback(err); @@ -336,7 +341,11 @@ Backend.prototype.getOps = function(agent, index, id, from, to, callback) { }); }; -Backend.prototype.getOpsBulk = function(agent, index, fromMap, toMap, callback) { +Backend.prototype.getOpsBulk = function(agent, index, fromMap, toMap, options, callback) { + if (typeof options === 'function') { + callback = options; + options = null; + } var start = Date.now(); var projection = this.projections[index]; var collection = (projection) ? projection.target : index; @@ -348,7 +357,8 @@ Backend.prototype.getOpsBulk = function(agent, index, fromMap, toMap, callback) fromMap: fromMap, toMap: toMap }; - backend.db.getOpsBulk(collection, fromMap, toMap, null, function(err, opsMap) { + var opsOptions = options && options.opsOptions; + backend.db.getOpsBulk(collection, fromMap, toMap, opsOptions, function(err, opsMap) { if (err) return callback(err); backend._sanitizeOpsBulk(agent, projection, collection, opsMap, function(err) { if (err) return callback(err); @@ -358,7 +368,11 @@ Backend.prototype.getOpsBulk = function(agent, index, fromMap, toMap, callback) }); }; -Backend.prototype.fetch = function(agent, index, id, callback) { +Backend.prototype.fetch = function(agent, index, id, options, callback) { + if (typeof options === 'function') { + callback = options; + options = null; + } var start = Date.now(); var projection = this.projections[index]; var collection = (projection) ? projection.target : index; @@ -370,7 +384,8 @@ Backend.prototype.fetch = function(agent, index, id, callback) { collection: collection, id: id }; - backend.db.getSnapshot(collection, id, fields, null, function(err, snapshot) { + var snapshotOptions = options && options.snapshotOptions; + backend.db.getSnapshot(collection, id, fields, snapshotOptions, function(err, snapshot) { if (err) return callback(err); var snapshotProjection = backend._getSnapshotProjection(backend.db, projection); var snapshots = [snapshot]; @@ -382,7 +397,11 @@ Backend.prototype.fetch = function(agent, index, id, callback) { }); }; -Backend.prototype.fetchBulk = function(agent, index, ids, callback) { +Backend.prototype.fetchBulk = function(agent, index, ids, options, callback) { + if (typeof options === 'function') { + callback = options; + options = null; + } var start = Date.now(); var projection = this.projections[index]; var collection = (projection) ? projection.target : index; @@ -394,7 +413,8 @@ Backend.prototype.fetchBulk = function(agent, index, ids, callback) { collection: collection, ids: ids }; - backend.db.getSnapshotBulk(collection, ids, fields, null, function(err, snapshotMap) { + var snapshotOptions = options && options.snapshotOptions; + backend.db.getSnapshotBulk(collection, ids, fields, snapshotOptions, function(err, snapshotMap) { if (err) return callback(err); var snapshotProjection = backend._getSnapshotProjection(backend.db, projection); var snapshots = backend._getSnapshotsFromMap(ids, snapshotMap); @@ -407,7 +427,18 @@ Backend.prototype.fetchBulk = function(agent, index, ids, callback) { }; // Subscribe to the document from the specified version or null version -Backend.prototype.subscribe = function(agent, index, id, version, callback) { +Backend.prototype.subscribe = function(agent, index, id, version, options, callback) { + if (typeof options === 'function') { + callback = options; + options = null; + } + if (options) { + // We haven't yet implemented the ability to pass options to subscribe. This is because we need to + // add the ability to SubmitRequest.commit to optionally pass the metadata to other clients on + // PubSub. This behaviour is not needed right now, but we have added an options object to the + // subscribe() signature so that it remains consistent with getOps() and fetch(). + return callback({code: 4025, message: 'Passing options to subscribe has not been implemented'}); + } var start = Date.now(); var projection = this.projections[index]; var collection = (projection) ? projection.target : index; diff --git a/test/backend.js b/test/backend.js new file mode 100644 index 000000000..d04746e2b --- /dev/null +++ b/test/backend.js @@ -0,0 +1,104 @@ +var Backend = require('../lib/backend'); +var expect = require('expect.js'); + +describe('Backend', function () { + var backend; + + beforeEach(function () { + backend = new Backend(); + }); + + afterEach(function (done) { + backend.close(done); + }); + + describe('a simple document', function () { + beforeEach(function (done) { + var doc = backend.connect().get('books', '1984'); + doc.create({ title: '1984' }, function (error) { + if (error) return done(error); + doc.submitOp({ p: ['author'], oi: 'George Orwell' }, done); + }); + }); + + describe('getOps', function () { + it('fetches all the ops', function (done) { + backend.getOps(null, 'books', '1984', 0, null, function (error, ops) { + if (error) return done(error); + expect(ops).to.have.length(2); + expect(ops[0].create.data).to.eql({ title: '1984' }); + expect(ops[1].op).to.eql([{ p: ['author'], oi: 'George Orwell' }]); + done(); + }); + }); + + it('fetches the ops with metadata', function (done) { + var options = { + opsOptions: {metadata: true} + }; + backend.getOps(null, 'books', '1984', 0, null, options, function (error, ops) { + if (error) return done(error); + expect(ops).to.have.length(2); + expect(ops[0].m).to.be.ok(); + expect(ops[1].m).to.be.ok(); + done(); + }); + }); + }); + + describe('fetch', function () { + it('fetches the document', function (done) { + backend.fetch(null, 'books', '1984', function (error, doc) { + if (error) return done(error); + expect(doc.data).to.eql({ + title: '1984', + author: 'George Orwell' + }); + done(); + }); + }); + + it('fetches the document with metadata', function (done) { + var options = { + snapshotOptions: {metadata: true} + }; + backend.fetch(null, 'books', '1984', options, function (error, doc) { + if (error) return done(error); + expect(doc.m).to.be.ok(); + done(); + }); + }); + }); + + describe('subscribe', function () { + it('subscribes to the document', function (done) { + backend.subscribe(null, 'books', '1984', null, function (error, stream, snapshot) { + if (error) return done(error); + expect(stream.open).to.be(true); + expect(snapshot.data).to.eql({ + title: '1984', + author: 'George Orwell' + }); + var op = {op: {p: ['publication'], oi: 1949}}; + stream.on('data', function (data) { + expect(data.op).to.eql(op.op); + done(); + }); + backend.submit(null, 'books', '1984', op, null, function (error) { + if (error) return done(error); + }); + }); + }); + + it('does not support subscribing to the document with options', function (done) { + var options = { + opsOptions: { metadata: true } + }; + backend.subscribe(null, 'books', '1984', null, options, function (error) { + expect(error.code).to.be(4025); + done(); + }); + }); + }); + }); +});