Skip to content

Instantly share code, notes, and snippets.

@garbados
Last active January 10, 2018 20:30
Show Gist options
  • Save garbados/335bc7c1836cbf726a6b511d6c0fa418 to your computer and use it in GitHub Desktop.
Save garbados/335bc7c1836cbf726a6b511d6c0fa418 to your computer and use it in GitHub Desktop.
A test case that produces conflicts, and then performs a mango query that should find only the conflicts, but also reports documents without conflicts.
#!/usr/bin/env node
'use strict'
/**
* A test case that produces conflicts,
* and then performs a mango query that
* should find only the conflicts, but also
* reports documents without conflicts.
*
* To run this script:
* $ mkdir test-conflict-index && cd $_
* $ curl https://gist.githubusercontent.com/garbados/335bc7c1836cbf726a6b511d6c0fa418/raw/c82d3f151c829449019bc0ec09ba77363d7f6b99/test-conflict-index.js test.js
* $ npm i async request
* $ node test.js
*
* Here are the approximate steps taken by the script:
*
* - add a document to one db
* - add a different document to the other
* - replicate it to the other
* - update the document on each db, but differently
* - replicate one to the other
* - now there is a conflict!
* - perform _find query
* - verify that it returns >1 doc
*/
const async = require('async')
const request = require('request')
const url = require('url')
const COUCH_URL = url.parse(process.env.COUCH_URL)
const SELECTOR = {
selector: { _id: { $exists: true } },
conflicts: true
}
// helper for turning [host, db, doc] into host/db/doc
const cJoin = function () {
const args = Object.values(arguments)
var href = COUCH_URL.href
if (href.slice(-1)[0] === '/') href = href.slice(0, -1)
return [href].concat(args).join('/')
}
var options = {
dbs: ['x', 'y'],
docs: [{ _id: 'a' }, { _id: 'b' }],
updates: [{ c: 'd' }, { d: 'e' }],
revs: []
}
function tearDown (done) {
async.times(2, function (i, done) {
var db = options.dbs[i]
request({
url: cJoin(db),
method: 'DELETE'
}, done)
}, done)
}
async.series([
// create two databases with one document each
async.times.bind(async, 2, function (i, done) {
var db = options.dbs[i]
var doc = options.docs[i]
async.series([
request.bind(request, {
url: cJoin(db),
method: 'PUT'
}),
request.bind(request, {
url: cJoin(db, doc._id),
method: 'PUT',
json: doc
})
// TODO collect doc results, add _rev to options.revs
], function (err, result) {
if (err) return done(err)
doc._rev = result[1][1].rev
return done()
})
}),
// replicate one to the other
function (done) {
request({
url: cJoin('_replicate'),
method: 'POST',
json: {
source: options.dbs[0],
target: options.dbs[1]
}
}, done)
},
// update the documents on each
async.times.bind(async, 2, function (i, done) {
var db = options.dbs[i]
var doc = options.docs[0]
var update = options.updates[i]
request({
url: cJoin(db, doc._id),
method: 'PUT',
json: Object.assign({}, doc, update)
}, done)
}),
// replicate again, creating the conflict
function (done) {
request({
url: cJoin('_replicate'),
method: 'POST',
json: {
source: options.dbs[0],
target: options.dbs[1]
}
}, done)
},
async.waterfall.bind(async, [
// perform the _find query
request.bind(request, {
url: cJoin(options.dbs[1], '_find'),
method: 'POST',
json: SELECTOR
}),
// verify that not all returns docs have conflicts
function (res, body, done) {
const db = options.dbs[1]
const docs = body.docs
console.log(body)
console.log(docs)
console.log('CouchDB reports %i docs with conflicts', docs.length)
console.log(' docs: %s', docs.map(doc => doc._id).join(', '))
async.each(docs, function (doc, done) {
request({
url: cJoin(db, doc._id),
qs: { conflicts: true }
}, function (err, res, body) {
if (err) return done(err)
const doc = JSON.parse(body)
console.log('Retrieved %s', doc._id)
console.log(' doc: %j', doc)
if (!doc._conflicts) {
console.log(' ... but it has no conflicts!')
}
return done()
})
}, done)
}
])
], function (err) {
if (err) console.log(err)
return tearDown()
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment