blob: 2fc661cbbac349c2b6ab1a7d36ab6cac74e329a5 [file] [log] [blame]
import { createError, MISSING_DOC, REV_CONFLICT } from 'pouchdb-errors';
import updateDoc from './updateDoc';
import {
isDeleted,
isLocalId,
merge,
winningRev as calculateWinningRev
} from 'pouchdb-merge';
function rootIsMissing(docInfo) {
return docInfo.metadata.rev_tree[0].ids[1].status === 'missing';
}
function processDocs(revLimit, docInfos, api, fetchedDocs, tx, results,
writeDoc, opts, overallCallback) {
// Default to 1000 locally
revLimit = revLimit || 1000;
function insertDoc(docInfo, resultsIdx, callback) {
// Cant insert new deleted documents
var winningRev = calculateWinningRev(docInfo.metadata);
var deleted = isDeleted(docInfo.metadata, winningRev);
if ('was_delete' in opts && deleted) {
results[resultsIdx] = createError(MISSING_DOC, 'deleted');
return callback();
}
// 4712 - detect whether a new document was inserted with a _rev
var inConflict = newEdits && rootIsMissing(docInfo);
if (inConflict) {
var err = createError(REV_CONFLICT);
results[resultsIdx] = err;
return callback();
}
var delta = deleted ? 0 : 1;
writeDoc(docInfo, winningRev, deleted, deleted, false,
delta, resultsIdx, callback);
}
var newEdits = opts.new_edits;
var idsToDocs = new Map();
var docsDone = 0;
var docsToDo = docInfos.length;
function checkAllDocsDone() {
if (++docsDone === docsToDo && overallCallback) {
overallCallback();
}
}
docInfos.forEach(function (currentDoc, resultsIdx) {
if (currentDoc._id && isLocalId(currentDoc._id)) {
var fun = currentDoc._deleted ? '_removeLocal' : '_putLocal';
api[fun](currentDoc, {ctx: tx}, function (err, res) {
results[resultsIdx] = err || res;
checkAllDocsDone();
});
return;
}
var id = currentDoc.metadata.id;
if (idsToDocs.has(id)) {
docsToDo--; // duplicate
idsToDocs.get(id).push([currentDoc, resultsIdx]);
} else {
idsToDocs.set(id, [[currentDoc, resultsIdx]]);
}
});
// in the case of new_edits, the user can provide multiple docs
// with the same id. these need to be processed sequentially
idsToDocs.forEach(function (docs, id) {
var numDone = 0;
function docWritten() {
if (++numDone < docs.length) {
nextDoc();
} else {
checkAllDocsDone();
}
}
function nextDoc() {
var value = docs[numDone];
var currentDoc = value[0];
var resultsIdx = value[1];
if (fetchedDocs.has(id)) {
updateDoc(revLimit, fetchedDocs.get(id), currentDoc, results,
resultsIdx, docWritten, writeDoc, newEdits);
} else {
// Ensure stemming applies to new writes as well
var merged = merge([], currentDoc.metadata.rev_tree[0], revLimit);
currentDoc.metadata.rev_tree = merged.tree;
currentDoc.stemmedRevs = merged.stemmedRevs || [];
insertDoc(currentDoc, resultsIdx, docWritten);
}
}
nextDoc();
});
}
export default processDocs;