refactor
diff --git a/lib/adapters/idb.js b/lib/adapters/idb.js index 1ce2e1c..e6783a0 100644 --- a/lib/adapters/idb.js +++ b/lib/adapters/idb.js
@@ -219,61 +219,64 @@ txn.objectStore(META_STORE).put(meta); } + function checkDoneWritingDocs() { + if (++numDocsWritten === docInfos.length) { + txn.objectStore(META_STORE).get(META_STORE).onsuccess = writeMetaData; + } + } + function processDocs() { if (!docInfos.length) { return; } - var idsToDocInfos = new utils.Map(); + var idsToDocs = new utils.Map(); - docInfos.forEach(function (currentDoc, i) { + docInfos.forEach(function (currentDoc, resultsIdx) { if (currentDoc._id && utils.isLocalId(currentDoc._id)) { api[currentDoc._deleted ? '_removeLocal' : '_putLocal']( currentDoc, {ctx: txn}, function (err, resp) { if (err) { - results[i] = err; + results[resultsIdx] = err; } else { - results[i] = {}; + results[resultsIdx] = {}; } - checkDone(); + checkDoneWritingDocs(); }); return; } var id = currentDoc.metadata.id; - - var arr; - if (idsToDocInfos.has(id)) { - arr = idsToDocInfos.get(id); + if (idsToDocs.has(id)) { + idsToDocs.get(id).push([currentDoc, resultsIdx]); } else { - arr = []; - idsToDocInfos.set(id, arr); + idsToDocs.set(id, [[currentDoc, resultsIdx]]); } - arr.push([currentDoc, i]); }); - idsToDocInfos.forEach(function (arr, id) { + // 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 checkArrDone() { - checkDone(); - if (++numDone < arr.length) { - next(); + function docWritten() { + checkDoneWritingDocs(); + if (++numDone < docs.length) { + nextDoc(); } } - function next() { - var value = arr[numDone]; + function nextDoc() { + var value = docs[numDone]; var currentDoc = value[0]; - var i = value[1]; + var resultsIdx = value[1]; if (fetchedDocs.has(id)) { - // if newEdits=false, can re-use the same id from this batch - return updateDoc(fetchedDocs.get(id), currentDoc, i, checkArrDone); + updateDoc(fetchedDocs.get(id), currentDoc, resultsIdx, docWritten); } else { - insertDoc(currentDoc, i, checkArrDone); + insertDoc(currentDoc, resultsIdx, docWritten); } } - next(); + nextDoc(); }); } @@ -409,7 +412,7 @@ } } - function writeDoc(docInfo, winningRev, deleted, callback, i) { + function writeDoc(docInfo, winningRev, deleted, callback, resultsIdx) { var err = null; var recv = 0; docInfo.data._id = docInfo.metadata.id; @@ -467,7 +470,7 @@ metaDataReq.onsuccess = function () { delete metadata.deletedOrLocal; delete metadata.winningRev; - results[i] = docInfo; + results[resultsIdx] = docInfo; fetchedDocs.set(docInfo.metadata.id, docInfo.metadata); utils.call(callback); }; @@ -494,7 +497,7 @@ } } - function updateDoc(oldDoc, docInfo, i, callback) { + function updateDoc(oldDoc, docInfo, resultsIdx, callback) { var merged = merge.merge(oldDoc.rev_tree, docInfo.metadata.rev_tree[0], 1000); var wasPreviouslyDeleted = utils.isDeleted(oldDoc); @@ -503,7 +506,7 @@ (!wasPreviouslyDeleted && newEdits && merged.conflicts !== 'new_leaf'); if (inConflict) { - results[i] = makeErr(errors.REV_CONFLICT, docInfo._bulk_seq); + results[resultsIdx] = makeErr(errors.REV_CONFLICT, docInfo._bulk_seq); return callback(); } @@ -513,25 +516,19 @@ var winningRev = merge.winningRev(docInfo.metadata); deleted = utils.isDeleted(docInfo.metadata, winningRev); - writeDoc(docInfo, winningRev, deleted, callback, i); + writeDoc(docInfo, winningRev, deleted, callback, resultsIdx); } - function insertDoc(docInfo, i, callback) { + function insertDoc(docInfo, resultsIdx, callback) { var winningRev = merge.winningRev(docInfo.metadata); var deleted = utils.isDeleted(docInfo.metadata, winningRev); // Cant insert new deleted documents if ('was_delete' in opts && deleted) { - results[i] = errors.MISSING_DOC; + results[resultsIdx] = errors.MISSING_DOC; return callback(); } - writeDoc(docInfo, winningRev, deleted, callback, i); - } - - function checkDone() { - if (++numDocsWritten === docInfos.length) { - txn.objectStore(META_STORE).get(META_STORE).onsuccess = writeMetaData; - } + writeDoc(docInfo, winningRev, deleted, callback, resultsIdx); } // Insert sequence number into the error so we can sort later
diff --git a/lib/adapters/websql.js b/lib/adapters/websql.js index 996d525..4c6f8ad 100644 --- a/lib/adapters/websql.js +++ b/lib/adapters/websql.js
@@ -573,7 +573,8 @@ } } - function writeDoc(docInfo, winningRev, deleted, callback, isUpdate, i) { + function writeDoc(docInfo, winningRev, deleted, callback, isUpdate, + resultsIdx) { function finish() { updateSeq++; @@ -668,14 +669,14 @@ [metadataStr, winningRev, id] : [id, seq, metadataStr]; tx.executeSql(sql, params, function () { - results[i] = docInfo; + results[resultsIdx] = docInfo; fetchedDocs.set(id, docInfo.metadata); callback(); }); } } - function updateDoc(oldDoc, docInfo, i, callback) { + function updateDoc(oldDoc, docInfo, resultsIdx, callback) { var merged = merge.merge(oldDoc.rev_tree, docInfo.metadata.rev_tree[0], 1000); var deleted = utils.isDeleted(docInfo.metadata); @@ -683,7 +684,7 @@ var inConflict = (oldDocDeleted && deleted && newEdits) || (!oldDocDeleted && newEdits && merged.conflicts !== 'new_leaf'); if (inConflict) { - results[i] = makeErr(errors.REV_CONFLICT, docInfo._bulk_seq); + results[resultsIdx] = makeErr(errors.REV_CONFLICT, docInfo._bulk_seq); return callback(); } @@ -693,21 +694,21 @@ var winningRev = merge.winningRev(docInfo.metadata); deleted = utils.isDeleted(docInfo.metadata, winningRev); - writeDoc(docInfo, winningRev, deleted, callback, true, i); + writeDoc(docInfo, winningRev, deleted, callback, true, resultsIdx); } - function insertDoc(docInfo, i, callback) { + function insertDoc(docInfo, resultsIdx, callback) { // Cant insert new deleted documents var winningRev = merge.winningRev(docInfo.metadata); var deleted = utils.isDeleted(docInfo.metadata, winningRev); if ('was_delete' in opts && deleted) { - results[i] = errors.MISSING_DOC; + results[resultsIdx] = errors.MISSING_DOC; return callback(); } - writeDoc(docInfo, winningRev, deleted, callback, false, i); + writeDoc(docInfo, winningRev, deleted, callback, false, resultsIdx); } - function checkDone() { + function checkDoneWritingDocs() { if (++numDocsWritten === docInfos.length) { complete(); } @@ -718,63 +719,58 @@ return complete(); } - var idsToDocInfos = new utils.Map(); + var idsToDocs = new utils.Map(); - docInfos.forEach(function (currentDoc, i) { + docInfos.forEach(function (currentDoc, resultsIdx) { if (currentDoc._id && utils.isLocalId(currentDoc._id)) { api[currentDoc._deleted ? '_removeLocal' : '_putLocal']( currentDoc, {ctx: tx}, function (err, resp) { if (err) { - results[i] = err; + results[resultsIdx] = err; } else { - results[i] = {}; + results[resultsIdx] = {}; } - checkDone(); + checkDoneWritingDocs(); }); return; } var id = currentDoc.metadata.id; - - var arr; - if (idsToDocInfos.has(id)) { - arr = idsToDocInfos.get(id); + if (idsToDocs.has(id)) { + idsToDocs.get(id).push([currentDoc, resultsIdx]); } else { - arr = []; - idsToDocInfos.set(id, arr); + idsToDocs.set(id, [[currentDoc, resultsIdx]]); } - arr.push([currentDoc, i]); }); - idsToDocInfos.forEach(function (arr, id) { - + // 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 checkArrDone() { - checkDone(); - if (++numDone < arr.length) { - next(); + function docWritten() { + checkDoneWritingDocs(); + if (++numDone < docs.length) { + nextDoc(); } } - function next() { - var value = arr[numDone]; + function nextDoc() { + var value = docs[numDone]; var currentDoc = value[0]; - var i = value[1]; + var resultsIdx = value[1]; if (fetchedDocs.has(id)) { - // if newEdits=false, can re-use the same id from this batch - return updateDoc(fetchedDocs.get(id), currentDoc, i, checkArrDone); + updateDoc(fetchedDocs.get(id), currentDoc, resultsIdx, docWritten); } else { - insertDoc(currentDoc, i, checkArrDone); + insertDoc(currentDoc, resultsIdx, docWritten); } } - next(); + nextDoc(); }); } function fetchExistingDocs(callback) { - // fetch all existing docs at once if (!docInfos.length) { return callback(); }