Skip to content

MongoDB 3.x driver #83

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Nov 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
language: node_js

node_js:
- "6"
- "8"
- "12"
- "10"
- "8"

services:
- docker

env:
- MONGODB_VERSION="2.6"
- MONGODB_VERSION="3.6"
- MONGODB_VERSION="4.2"
- MONGODB_VERSION="4.0"
- MONGODB_VERSION="3.6"
- MONGODB_VERSION="3.4"

before_install:
- docker run -d -p 127.0.0.1:27017:27017 mongo:$MONGODB_VERSION
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ together with snapshots.

## Usage

`sharedb-mongo` wraps native [mongodb](https://github.com/mongodb/node-mongodb-native), and it supports the same configuration options.
`sharedb-mongo` uses the [MongoDB NodeJS Driver](https://github.com/mongodb/node-mongodb-native), and it supports the same configuration options.

There are two ways to instantiate a sharedb-mongo wrapper:

1. The simplest way is to invoke the module and pass in your mongo DB
arguments as arguments to the module function. For example:

```javascript
const db = require('sharedb-mongo')('mongodb://localhost:27017/test');
const db = require('sharedb-mongo')('mongodb://localhost:27017/test', {mongoOptions: {...}});
const backend = new ShareDB({db});
```

Expand Down
51 changes: 40 additions & 11 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ function ShareDbMongo(mongo, options) {
// We can only get the mongodb client instance in a callback, so
// buffer up any requests received in the meantime
this.mongo = null;
this._mongoClient = null;
this.mongoPoll = null;
this._mongoPollClient = null;
this.pendingConnect = [];
this._connect(mongo, options);
} else {
Expand Down Expand Up @@ -125,6 +127,16 @@ ShareDbMongo.prototype._flushPendingConnect = function() {
}
};

function isLegacyMongoClient(client) {
// mongodb 2.0 connect returns a DB object that also implements the
// functionality of client, such as `close()`. mongodb 3.0 connect returns a
// Client without the `collection()` method
return (
typeof client.collection === 'function' &&
typeof client.close === 'function'
);
}

ShareDbMongo.prototype._connect = function(mongo, options) {
// Create the mongo connection client connections if needed
//
Expand All @@ -137,32 +149,49 @@ ShareDbMongo.prototype._connect = function(mongo, options) {
tasks = {mongo: mongo, mongoPoll: options.mongoPoll};
} else {
tasks = {
mongo: function(parallelCb) {
mongoClient: function(parallelCb) {
mongodb.connect(mongo, options.mongoOptions, parallelCb);
},
mongoPoll: function(parallelCb) {
mongoPollClient: function(parallelCb) {
mongodb.connect(options.mongoPoll, options.mongoPollOptions, parallelCb);
}
};
}
async.parallel(tasks, function(err, results) {
if (err) throw err;
self.mongo = results.mongo;
self.mongoPoll = results.mongoPoll;
var mongoClient = results.mongoClient;
var mongoPollClient = results.mongoPollClient;
if (isLegacyMongoClient(mongoClient)) {
self.mongo = self._mongoClient = mongoClient;
self.mongoPoll = self._mongoPollClient = mongoPollClient;
} else {
self.mongo = mongoClient.db();
self._mongoClient = mongoClient;
self.mongoPoll = mongoPollClient.db();
self._mongoPollClient = mongoPollClient;
}
self._flushPendingConnect();
});
return;
}
var finish = function(err, db) {
var finish = function(err, client) {
if (err) throw err;
self.mongo = db;
if (isLegacyMongoClient(client)) {
self.mongo = self._mongoClient = client;
} else {
self.mongo = client.db();
self._mongoClient = client;
}
self._flushPendingConnect();
};
if (typeof mongo === 'function') {
mongo(finish);
return;
}
mongodb.connect(mongo, options, finish);
// TODO: Don't pass options directly to mongodb.connect();
// only pass options.mongoOptions
var mongoOptions = options.mongoOptions || options;
mongodb.connect(mongo, mongoOptions, finish);
};

ShareDbMongo.prototype.close = function(callback) {
Expand All @@ -172,13 +201,13 @@ ShareDbMongo.prototype.close = function(callback) {
};
}
var self = this;
this.getDbs(function(err, mongo, mongoPoll) {
this.getDbs(function(err) {
if (err) return callback(err);
self.closed = true;
mongo.close(function(err) {
self._mongoClient.close(function(err) {
if (err) return callback(err);
if (!mongoPoll) return callback();
mongoPoll.close(callback);
if (!self._mongoPollClient) return callback();
self._mongoPollClient.close(callback);
});
});
};
Expand Down
16 changes: 8 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,25 @@
"description": "MongoDB database adapter for ShareDB",
"main": "index.js",
"dependencies": {
"async": "^1.4.2",
"mongodb": "^2.1.2",
"async": "^1.5.2",
"mongodb": "^2.1.2 || ^3.0.0",
"sharedb": "^1.0.0-beta"
},
"devDependencies": {
"coveralls": "^2.11.8",
"chai": "^4.2.0",
"coveralls": "^3.0.7",
"eslint": "^5.16.0",
"eslint-config-google": "^0.13.0",
"expect.js": "^0.3.1",
"istanbul": "^0.4.2",
"mocha": "^2.3.3",
"sharedb-mingo-memory": "^1.0.2",
"mocha": "^6.2.2",
"nyc": "^14.1.1",
"sharedb-mingo-memory": "^1.1.1",
"sinon": "^6.1.5"
},
"scripts": {
"lint": "./node_modules/.bin/eslint --ignore-path .gitignore '**/*.js'",
"lint:fix": "npm run lint -- --fix",
"test": "npm run lint && node_modules/.bin/mocha",
"test-cover": "npm run lint && node_modules/istanbul/lib/cli.js cover node_modules/mocha/bin/_mocha"
"test-cover": "npm run lint && node_modules/nyc/bin/nyc.js --temp-dir=coverage -r text -r lcov node_modules/mocha/bin/_mocha"
},
"repository": "git://github.com/share/sharedb-mongo.git",
"author": "Nate Smith and Joseph Gentle",
Expand Down
59 changes: 28 additions & 31 deletions test/test_get_ops_without_strict_linking.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,22 @@
var expect = require('expect.js');
var mongodb = require('mongodb');
var expect = require('chai').expect;
var ShareDbMongo = require('..');
var getQuery = require('sharedb-mingo-memory/get-query');
var sinon = require('sinon');

var mongoUrl = process.env.TEST_MONGO_URL || 'mongodb://localhost:27017/test';

function create(callback) {
var db = new ShareDbMongo({
mongo: function(shareDbCallback) {
mongodb.connect(mongoUrl, function(err, mongo) {
if (err) return callback(err);
mongo.dropDatabase(function(err) {
if (err) return callback(err);
shareDbCallback(null, mongo);
callback(null, db, mongo);
});
});
},
var db = new ShareDbMongo(mongoUrl, {
mongoOptions: {},
getOpsWithoutStrictLinking: true
});
db.getDbs(function(err, mongo) {
if (err) return callback(err);
mongo.dropDatabase(function(err) {
if (err) return callback(err);
callback(null, db, mongo);
});
});
};

require('sharedb/test/db')({create: create, getQuery: getQuery});
Expand Down Expand Up @@ -67,11 +64,11 @@ describe('getOpsWithoutStrictLinking: true', function() {
it('fetches ops 0-1 without fetching all ops', function(done) {
db.getOps(collection, id, 0, 2, null, function(error, ops) {
if (error) return done(error);
expect(ops.length).to.be(2);
expect(ops[0].v).to.be(0);
expect(ops[1].v).to.be(1);
expect(db._getSnapshotOpLink.notCalled).to.be(true);
expect(db._getOps.calledOnceWith(collection, id, 0, 2)).to.be(true);
expect(ops.length).to.equal(2);
expect(ops[0].v).to.equal(0);
expect(ops[1].v).to.equal(1);
expect(db._getSnapshotOpLink.notCalled).to.equal(true);
expect(db._getOps.calledOnceWith(collection, id, 0, 2)).to.equal(true);
done();
});
});
Expand All @@ -81,16 +78,16 @@ describe('getOpsWithoutStrictLinking: true', function() {

callInSeries([
function(next) {
mongo.collection('o_' + collection).insert(spuriousOp, next);
mongo.collection('o_' + collection).insertOne(spuriousOp, next);
},
function(result, next) {
db.getOps(collection, id, 0, 2, null, next);
},
function(ops, next) {
expect(ops.length).to.be(2);
expect(ops[1].oi).to.be('bar');
expect(db._getSnapshotOpLink.notCalled).to.be(true);
expect(db._getOps.calledOnceWith(collection, id, 0, 2)).to.be(true);
expect(ops.length).to.equal(2);
expect(ops[1].oi).to.equal('bar');
expect(db._getSnapshotOpLink.notCalled).to.equal(true);
expect(db._getOps.calledOnceWith(collection, id, 0, 2)).to.equal(true);
next();
},
done
Expand All @@ -102,16 +99,16 @@ describe('getOpsWithoutStrictLinking: true', function() {

callInSeries([
function(next) {
mongo.collection('o_' + collection).insert(spuriousOp, next);
mongo.collection('o_' + collection).insertOne(spuriousOp, next);
},
function(result, next) {
db.getOps(collection, id, 0, 2, null, next);
},
function(ops, next) {
expect(ops.length).to.be(2);
expect(ops[1].oi).to.be('bar');
expect(db._getSnapshotOpLink.notCalled).to.be(true);
expect(db._getOps.calledOnceWith(collection, id, 0, 3)).to.be(true);
expect(ops.length).to.equal(2);
expect(ops[1].oi).to.equal('bar');
expect(db._getSnapshotOpLink.notCalled).to.equal(true);
expect(db._getOps.calledOnceWith(collection, id, 0, 3)).to.equal(true);
next();
},
done
Expand All @@ -134,10 +131,10 @@ describe('getOpsWithoutStrictLinking: true', function() {
db.getOps(collection, id, 0, 2, null, next);
},
function(ops, next) {
expect(ops.length).to.be(2);
expect(ops.length).to.equal(2);
expect(ops[0].create).to.eql({});
expect(ops[1].oi).to.be('bar');
expect(db._getSnapshotOpLink.calledOnce).to.be(true);
expect(ops[1].oi).to.equal('bar');
expect(db._getSnapshotOpLink.calledOnce).to.equal(true);
next();
},
done
Expand Down
Loading