blob: eb36a6aceeceae7e986103d877830cee4e285410 [file] [log] [blame]
'use strict';
var PouchDB = require('../../packages/node_modules/pouchdb-for-coverage');
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.json());
app.get('*', countLocalGETs);
app.use(require('pouchdb-express-router')(PouchDB));
var localGETCount = 0;
function countLocalGETs(req, res, next) {
// undesired behaviour hits this endpoint more times than numDocs
if (req.url.indexOf('/remote/_local/') === 0) {
localGETCount++;
}
next();
}
require('chai').should();
describe('test.replication_perf_regression.js', function () {
var server;
var dbs;
before(function () {
server = app.listen(0);
dbs = {
name: 'test',
remote: 'http://127.0.0.1:' + server.address().port + '/remote'
};
});
after(function () {
return server.close();
});
it('#5199 fix excessively long replication loop', function () {
this.timeout(5000); // mocha timeout increased for this test
var numDocs = 59; // uneven number...using smaller number for faster test
var docs = [];
for (var i = 0; i < numDocs; i++) {
// mix of generation-1 and generation-2 docs
if (i % 2 === 0) {
docs.push({
_id: 'testdoc_' + i,
_rev: '1-x',
_revisions: { start: 1, ids: ['x'] }
});
} else {
docs.push({
_id: 'testdoc_' + i,
_rev: '2-x',
_revisions: { start: 2, ids: ['x', 'y'] }
});
}
}
var db = new PouchDB(dbs.name);
var remote = new PouchDB(dbs.remote);
return remote.destroy().then(function () {
// init local & remote db (want both empty)
return db.destroy();
}).then(function () {
db = new PouchDB(dbs.name);
remote = new PouchDB(dbs.remote);
return remote.bulkDocs({
// to repro issue: docs exist at remote...nothing at local
docs: docs,
new_edits: false
});
}).then(function () {
function replicatePromise(fromDB, toDB) {
var debouncePauseActiveThrash_timeoutRef;
return new Promise(function (resolve, reject) {
var replication = fromDB.replicate.to(toDB, {
live: true,
retry: true,
batches_limit: 10,
batch_size: 100
}).on('paused', function (err) {
clearTimeout(debouncePauseActiveThrash_timeoutRef);
if (!err) {
// debounce pause -> active -> pause -> active etc
debouncePauseActiveThrash_timeoutRef = setTimeout(function () {
replication.cancel();
}, 1500);
}
}).on('active', function () {
clearTimeout(debouncePauseActiveThrash_timeoutRef);
}).on('complete', resolve)
.on('error', reject);
});
}
return Promise.all([
replicatePromise(db, remote),
replicatePromise(remote, db)
]);
}).then(function () {
return db.info();
}).then(function (info) {
info.doc_count.should.equal(numDocs); // should have replicated to local db
localGETCount.should.above(0); // should have hit /remote/_local endpoint at least once
localGETCount.should.below(numDocs); // localGETCount should be significantly below numDocs (~9x)
return db.destroy();
}).then(function () {
return remote.destroy();
});
});
});