Merge pull request #15719 from overleaf/em-promisify-mongo-manager

Promisify MongoManager

GitOrigin-RevId: e9e71a1865734ae202270d5b4fdaa6ba51fadab6
This commit is contained in:
Eric Mc Sween 2024-01-18 08:00:51 -05:00 committed by Copybot
parent 612c7c28b0
commit 29d41497ef
2 changed files with 254 additions and 340 deletions

View file

@ -1,28 +1,25 @@
const { db, ObjectId } = require('./mongodb')
const logger = require('@overleaf/logger')
const metrics = require('@overleaf/metrics')
const Settings = require('@overleaf/settings')
const OError = require('@overleaf/o-error')
const Errors = require('./Errors')
const { promisify } = require('util')
const { callbackify } = require('util')
const ARCHIVING_LOCK_DURATION_MS = Settings.archivingLockDurationMs
function findDoc(projectId, docId, filter, callback) {
db.docs.findOne(
async function findDoc(projectId, docId, filter) {
const doc = await db.docs.findOne(
{
_id: new ObjectId(docId.toString()),
project_id: new ObjectId(projectId.toString()),
},
{
projection: filter,
},
callback
}
)
return doc
}
function getProjectsDeletedDocs(projectId, filter, callback) {
db.docs
async function getProjectsDeletedDocs(projectId, filter) {
const docs = await db.docs
.find(
{
project_id: new ObjectId(projectId.toString()),
@ -34,10 +31,11 @@ function getProjectsDeletedDocs(projectId, filter, callback) {
limit: Settings.max_deleted_docs,
}
)
.toArray(callback)
.toArray()
return docs
}
function getProjectsDocs(projectId, options, filter, callback) {
async function getProjectsDocs(projectId, options, filter) {
const query = { project_id: new ObjectId(projectId.toString()) }
if (!options.include_deleted) {
query.deleted = { $ne: true }
@ -48,21 +46,23 @@ function getProjectsDocs(projectId, options, filter, callback) {
if (options.limit) {
queryOptions.limit = options.limit
}
db.docs.find(query, queryOptions).toArray(callback)
const docs = await db.docs.find(query, queryOptions).toArray()
return docs
}
function getArchivedProjectDocs(projectId, maxResults, callback) {
async function getArchivedProjectDocs(projectId, maxResults) {
const query = {
project_id: new ObjectId(projectId.toString()),
inS3: true,
}
db.docs
const docs = await db.docs
.find(query, { projection: { _id: 1 }, limit: maxResults })
.toArray(callback)
.toArray()
return docs
}
function getNonArchivedProjectDocIds(projectId, callback) {
db.docs
async function getNonArchivedProjectDocIds(projectId) {
const docs = await db.docs
.find(
{
project_id: new ObjectId(projectId),
@ -71,27 +71,23 @@ function getNonArchivedProjectDocIds(projectId, callback) {
{ projection: { _id: 1 } }
)
.map(doc => doc._id)
.toArray(callback)
.toArray()
return docs
}
function getNonDeletedArchivedProjectDocs(projectId, maxResults, callback) {
async function getNonDeletedArchivedProjectDocs(projectId, maxResults) {
const query = {
project_id: new ObjectId(projectId.toString()),
deleted: { $ne: true },
inS3: true,
}
db.docs
const docs = await db.docs
.find(query, { projection: { _id: 1 }, limit: maxResults })
.toArray(callback)
.toArray()
return docs
}
function upsertIntoDocCollection(
projectId,
docId,
previousRev,
updates,
callback
) {
async function upsertIntoDocCollection(projectId, docId, previousRev, updates) {
if (previousRev) {
const update = {
$set: updates,
@ -100,51 +96,43 @@ function upsertIntoDocCollection(
if (updates.lines || updates.ranges) {
update.$inc = { rev: 1 }
}
db.docs.updateOne(
const result = await db.docs.updateOne(
{
_id: new ObjectId(docId),
project_id: new ObjectId(projectId),
rev: previousRev,
},
update,
(err, result) => {
if (err) return callback(err)
if (result.matchedCount !== 1) {
return callback(new Errors.DocRevValueError())
}
callback()
}
update
)
if (result.matchedCount !== 1) {
throw new Errors.DocRevValueError()
}
} else {
db.docs.insertOne(
{
try {
await db.docs.insertOne({
_id: new ObjectId(docId),
project_id: new ObjectId(projectId),
rev: 1,
...updates,
},
err => {
if (err) {
if (err.code === 11000) {
// duplicate doc _id
return callback(new Errors.DocRevValueError())
}
return callback(err)
}
callback()
})
} catch (err) {
if (err.code === 11000) {
// duplicate doc _id
throw new Errors.DocRevValueError()
} else {
throw err
}
)
}
}
}
function patchDoc(projectId, docId, meta, callback) {
db.docs.updateOne(
async function patchDoc(projectId, docId, meta) {
await db.docs.updateOne(
{
_id: new ObjectId(docId),
project_id: new ObjectId(projectId),
},
{ $set: meta },
callback
{ $set: meta }
)
}
@ -154,9 +142,9 @@ function patchDoc(projectId, docId, meta, callback) {
* This will return null if the doc is not found, if it's already archived or
* if the lock can't be acquired.
*/
function getDocForArchiving(projectId, docId, callback) {
async function getDocForArchiving(projectId, docId) {
const archivingUntil = new Date(Date.now() + ARCHIVING_LOCK_DURATION_MS)
db.docs.findOneAndUpdate(
const result = await db.docs.findOneAndUpdate(
{
_id: new ObjectId(docId),
project_id: new ObjectId(projectId),
@ -167,27 +155,21 @@ function getDocForArchiving(projectId, docId, callback) {
{
projection: { lines: 1, ranges: 1, rev: 1 },
includeResultMetadata: true,
},
(err, result) => {
if (err) {
return callback(err)
}
callback(null, result.value)
}
)
return result.value
}
/**
* Clear the doc contents from Mongo and release the archiving lock
*/
function markDocAsArchived(projectId, docId, rev, callback) {
db.docs.updateOne(
async function markDocAsArchived(projectId, docId, rev) {
await db.docs.updateOne(
{ _id: new ObjectId(docId), rev },
{
$set: { inS3: true },
$unset: { lines: 1, ranges: 1, archivingUntil: 1 },
},
callback
}
)
}
@ -196,7 +178,7 @@ function markDocAsArchived(projectId, docId, rev, callback) {
*
* This checks that the archived doc's rev matches.
*/
function restoreArchivedDoc(projectId, docId, archivedDoc, callback) {
async function restoreArchivedDoc(projectId, docId, archivedDoc) {
const query = {
_id: new ObjectId(docId),
project_id: new ObjectId(projectId),
@ -211,60 +193,34 @@ function restoreArchivedDoc(projectId, docId, archivedDoc, callback) {
inS3: true,
},
}
db.docs.updateOne(query, update, (err, result) => {
if (err) {
OError.tag(err, 'failed to unarchive doc', {
docId,
rev: archivedDoc.rev,
})
return callback(err)
}
if (result.matchedCount === 0) {
return callback(
new Errors.DocRevValueError('failed to unarchive doc', {
docId,
rev: archivedDoc.rev,
})
)
}
callback()
})
const result = await db.docs.updateOne(query, update)
if (result.matchedCount === 0) {
throw new Errors.DocRevValueError('failed to unarchive doc', {
docId,
rev: archivedDoc.rev,
})
}
}
function getDocVersion(docId, callback) {
db.docOps.findOne(
{
doc_id: new ObjectId(docId),
},
async function getDocVersion(docId) {
const doc = await db.docOps.findOne(
{ doc_id: new ObjectId(docId) },
{
projection: {
version: 1,
},
},
function (error, doc) {
if (error) {
return callback(error)
}
callback(null, (doc && doc.version) || 0)
}
)
return (doc && doc.version) || 0
}
function getDocRev(docId, callback) {
db.docs.findOne(
{
_id: new ObjectId(docId.toString()),
},
{
projection: { rev: 1 },
},
function (err, doc) {
if (err) {
return callback(err)
}
callback(null, doc && doc.rev)
}
async function getDocRev(docId) {
const doc = await db.docs.findOne(
{ _id: new ObjectId(docId.toString()) },
{ projection: { rev: 1 } }
)
return doc && doc.rev
}
/**
@ -273,68 +229,64 @@ function getDocRev(docId, callback) {
* Check that the rev of an existing doc is unchanged. If the rev has
* changed, return a DocModifiedError.
*/
function checkRevUnchanged(doc, callback) {
getDocRev(doc._id, function (err, currentRev) {
if (err) return callback(err)
if (isNaN(currentRev) || isNaN(doc.rev)) {
return callback(
new Errors.DocRevValueError('doc rev is NaN', {
doc_id: doc._id,
rev: doc.rev,
currentRev,
})
)
}
if (doc.rev !== currentRev) {
return callback(
new Errors.DocModifiedError('doc rev has changed', {
doc_id: doc._id,
rev: doc.rev,
currentRev,
})
)
}
callback()
})
async function checkRevUnchanged(doc) {
const currentRev = await getDocRev(doc._id)
if (isNaN(currentRev) || isNaN(doc.rev)) {
throw new Errors.DocRevValueError('doc rev is NaN', {
doc_id: doc._id,
rev: doc.rev,
currentRev,
})
}
if (doc.rev !== currentRev) {
throw new Errors.DocModifiedError('doc rev has changed', {
doc_id: doc._id,
rev: doc.rev,
currentRev,
})
}
}
function destroyProject(projectId, callback) {
db.docs
async function destroyProject(projectId) {
const records = await db.docs
.find({ project_id: new ObjectId(projectId) }, { projection: { _id: 1 } })
.toArray((err, records) => {
const docIds = records.map(r => r._id)
if (err) {
return callback(err)
}
db.docOps.deleteMany({ doc_id: { $in: docIds } }, err => {
if (err) {
return callback(err)
}
db.docs.deleteMany({ project_id: new ObjectId(projectId) }, callback)
})
})
.toArray()
const docIds = records.map(r => r._id)
await db.docOps.deleteMany({ doc_id: { $in: docIds } })
await db.docs.deleteMany({ project_id: new ObjectId(projectId) })
}
module.exports = {
findDoc,
getProjectsDeletedDocs,
getProjectsDocs,
getArchivedProjectDocs,
getNonArchivedProjectDocIds,
getNonDeletedArchivedProjectDocs,
upsertIntoDocCollection,
restoreArchivedDoc,
patchDoc,
getDocForArchiving,
markDocAsArchived,
getDocVersion,
checkRevUnchanged,
destroyProject,
}
const methods = Object.getOwnPropertyNames(module.exports)
module.exports.promises = {}
for (const method of methods) {
metrics.timeAsyncMethod(module.exports, method, 'mongo.MongoManager', logger)
module.exports.promises[method] = promisify(module.exports[method])
findDoc: callbackify(findDoc),
getProjectsDeletedDocs: callbackify(getProjectsDeletedDocs),
getProjectsDocs: callbackify(getProjectsDocs),
getArchivedProjectDocs: callbackify(getArchivedProjectDocs),
getNonArchivedProjectDocIds: callbackify(getNonArchivedProjectDocIds),
getNonDeletedArchivedProjectDocs: callbackify(
getNonDeletedArchivedProjectDocs
),
upsertIntoDocCollection: callbackify(upsertIntoDocCollection),
restoreArchivedDoc: callbackify(restoreArchivedDoc),
patchDoc: callbackify(patchDoc),
getDocForArchiving: callbackify(getDocForArchiving),
markDocAsArchived: callbackify(markDocAsArchived),
getDocVersion: callbackify(getDocVersion),
checkRevUnchanged: callbackify(checkRevUnchanged),
destroyProject: callbackify(destroyProject),
promises: {
findDoc,
getProjectsDeletedDocs,
getProjectsDocs,
getArchivedProjectDocs,
getNonArchivedProjectDocIds,
getNonDeletedArchivedProjectDocs,
upsertIntoDocCollection,
restoreArchivedDoc,
patchDoc,
getDocForArchiving,
markDocAsArchived,
getDocVersion,
checkRevUnchanged,
destroyProject,
},
}

View file

@ -12,8 +12,8 @@ describe('MongoManager', function () {
beforeEach(function () {
this.db = {
docs: {
updateOne: sinon.stub().yields(null, { matchedCount: 1 }),
insertOne: sinon.stub().yields(null),
updateOne: sinon.stub().resolves({ matchedCount: 1 }),
insertOne: sinon.stub().resolves(),
},
docOps: {},
}
@ -34,21 +34,19 @@ describe('MongoManager', function () {
this.projectId = new ObjectId().toString()
this.docId = new ObjectId().toString()
this.rev = 42
this.callback = sinon.stub()
this.stubbedErr = new Error('hello world')
this.lines = ['Three French hens', 'Two turtle doves']
})
describe('findDoc', function () {
beforeEach(function () {
beforeEach(async function () {
this.doc = { name: 'mock-doc' }
this.db.docs.findOne = sinon.stub().callsArgWith(2, null, this.doc)
this.db.docs.findOne = sinon.stub().resolves(this.doc)
this.filter = { lines: true }
this.MongoManager.findDoc(
this.result = await this.MongoManager.promises.findDoc(
this.projectId,
this.docId,
this.filter,
this.callback
this.filter
)
})
@ -66,20 +64,18 @@ describe('MongoManager', function () {
.should.equal(true)
})
it('should call the callback with the doc', function () {
this.callback.calledWith(null, this.doc).should.equal(true)
it('should return the doc', function () {
expect(this.doc).to.deep.equal(this.doc)
})
})
describe('patchDoc', function () {
beforeEach(function (done) {
beforeEach(async function () {
this.meta = { name: 'foo.tex' }
this.callback.callsFake(done)
this.MongoManager.patchDoc(
await this.MongoManager.promises.patchDoc(
this.projectId,
this.docId,
this.meta,
this.callback
this.meta
)
})
@ -91,8 +87,7 @@ describe('MongoManager', function () {
},
{
$set: this.meta,
},
this.callback
}
)
})
})
@ -105,19 +100,16 @@ describe('MongoManager', function () {
this.doc3 = { name: 'mock-doc3' }
this.doc4 = { name: 'mock-doc4' }
this.db.docs.find = sinon.stub().returns({
toArray: sinon
.stub()
.callsArgWith(0, null, [this.doc, this.doc3, this.doc4]),
toArray: sinon.stub().resolves([this.doc, this.doc3, this.doc4]),
})
})
describe('with included_deleted = false', function () {
beforeEach(function () {
this.MongoManager.getProjectsDocs(
beforeEach(async function () {
this.result = await this.MongoManager.promises.getProjectsDocs(
this.projectId,
{ include_deleted: false },
this.filter,
this.callback
this.filter
)
})
@ -135,20 +127,17 @@ describe('MongoManager', function () {
.should.equal(true)
})
it('should call the callback with the docs', function () {
this.callback
.calledWith(null, [this.doc, this.doc3, this.doc4])
.should.equal(true)
it('should call return the docs', function () {
expect(this.result).to.deep.equal([this.doc, this.doc3, this.doc4])
})
})
describe('with included_deleted = true', function () {
beforeEach(function () {
this.MongoManager.getProjectsDocs(
beforeEach(async function () {
this.result = await this.MongoManager.promises.getProjectsDocs(
this.projectId,
{ include_deleted: true },
this.filter,
this.callback
this.filter
)
})
@ -165,28 +154,24 @@ describe('MongoManager', function () {
.should.equal(true)
})
it('should call the callback with the docs', function () {
this.callback
.calledWith(null, [this.doc, this.doc3, this.doc4])
.should.equal(true)
it('should return the docs', function () {
expect(this.result).to.deep.equal([this.doc, this.doc3, this.doc4])
})
})
})
describe('getProjectsDeletedDocs', function () {
beforeEach(function (done) {
beforeEach(async function () {
this.filter = { name: true }
this.doc1 = { _id: '1', name: 'mock-doc1.tex' }
this.doc2 = { _id: '2', name: 'mock-doc2.tex' }
this.doc3 = { _id: '3', name: 'mock-doc3.tex' }
this.db.docs.find = sinon.stub().returns({
toArray: sinon.stub().yields(null, [this.doc1, this.doc2, this.doc3]),
toArray: sinon.stub().resolves([this.doc1, this.doc2, this.doc3]),
})
this.callback.callsFake(done)
this.MongoManager.getProjectsDeletedDocs(
this.result = await this.MongoManager.promises.getProjectsDeletedDocs(
this.projectId,
this.filter,
this.callback
this.filter
)
})
@ -209,10 +194,8 @@ describe('MongoManager', function () {
.should.equal(true)
})
it('should call the callback with the docs', function () {
this.callback
.calledWith(null, [this.doc1, this.doc2, this.doc3])
.should.equal(true)
it('should return the docs', function () {
expect(this.result).to.deep.equal([this.doc1, this.doc2, this.doc3])
})
})
@ -221,108 +204,97 @@ describe('MongoManager', function () {
this.oldRev = 77
})
it('should upsert the document', function (done) {
this.MongoManager.upsertIntoDocCollection(
it('should upsert the document', async function () {
await this.MongoManager.promises.upsertIntoDocCollection(
this.projectId,
this.docId,
this.oldRev,
{ lines: this.lines },
err => {
assert.equal(err, null)
const args = this.db.docs.updateOne.args[0]
assert.deepEqual(args[0], {
_id: new ObjectId(this.docId),
project_id: new ObjectId(this.projectId),
rev: this.oldRev,
})
assert.equal(args[1].$set.lines, this.lines)
assert.equal(args[1].$inc.rev, 1)
done()
}
{ lines: this.lines }
)
const args = this.db.docs.updateOne.args[0]
assert.deepEqual(args[0], {
_id: new ObjectId(this.docId),
project_id: new ObjectId(this.projectId),
rev: this.oldRev,
})
assert.equal(args[1].$set.lines, this.lines)
assert.equal(args[1].$inc.rev, 1)
})
it('should handle update error', function (done) {
this.db.docs.updateOne.yields(this.stubbedErr)
this.MongoManager.upsertIntoDocCollection(
this.projectId,
this.docId,
this.rev,
{ lines: this.lines },
err => {
err.should.equal(this.stubbedErr)
done()
}
)
})
it('should insert without a previous rev', function (done) {
this.MongoManager.upsertIntoDocCollection(
this.projectId,
this.docId,
null,
{ lines: this.lines, ranges: this.ranges },
err => {
expect(this.db.docs.insertOne).to.have.been.calledWith({
_id: new ObjectId(this.docId),
project_id: new ObjectId(this.projectId),
rev: 1,
it('should handle update error', async function () {
this.db.docs.updateOne.rejects(this.stubbedErr)
await expect(
this.MongoManager.promises.upsertIntoDocCollection(
this.projectId,
this.docId,
this.rev,
{
lines: this.lines,
ranges: this.ranges,
})
expect(err).to.not.exist
done()
}
)
}
)
).to.be.rejectedWith(this.stubbedErr)
})
it('should handle generic insert error', function (done) {
this.db.docs.insertOne.yields(this.stubbedErr)
this.MongoManager.upsertIntoDocCollection(
it('should insert without a previous rev', async function () {
await this.MongoManager.promises.upsertIntoDocCollection(
this.projectId,
this.docId,
null,
{ lines: this.lines, ranges: this.ranges },
err => {
expect(err).to.equal(this.stubbedErr)
done()
}
{ lines: this.lines, ranges: this.ranges }
)
expect(this.db.docs.insertOne).to.have.been.calledWith({
_id: new ObjectId(this.docId),
project_id: new ObjectId(this.projectId),
rev: 1,
lines: this.lines,
ranges: this.ranges,
})
})
it('should handle duplicate insert error', function (done) {
this.db.docs.insertOne.yields({ code: 11000 })
this.MongoManager.upsertIntoDocCollection(
this.projectId,
this.docId,
null,
{ lines: this.lines, ranges: this.ranges },
err => {
expect(err).to.be.instanceof(Errors.DocRevValueError)
done()
}
)
it('should handle generic insert error', async function () {
this.db.docs.insertOne.rejects(this.stubbedErr)
await expect(
this.MongoManager.promises.upsertIntoDocCollection(
this.projectId,
this.docId,
null,
{ lines: this.lines, ranges: this.ranges }
)
).to.be.rejectedWith(this.stubbedErr)
})
it('should handle duplicate insert error', async function () {
this.db.docs.insertOne.rejects({ code: 11000 })
await expect(
this.MongoManager.promises.upsertIntoDocCollection(
this.projectId,
this.docId,
null,
{ lines: this.lines, ranges: this.ranges }
)
).to.be.rejectedWith(Errors.DocRevValueError)
})
})
describe('destroyProject', function () {
beforeEach(function (done) {
beforeEach(async function () {
this.projectId = new ObjectId()
this.docIds = [new ObjectId(), new ObjectId()]
this.db.docs.deleteMany = sinon.stub().yields()
this.db.docOps.deleteMany = sinon.stub().yields()
this.db.docs.deleteMany = sinon.stub().resolves()
this.db.docOps.deleteMany = sinon.stub().resolves()
this.db.docs.find = sinon
.stub()
.withArgs({ project_id: this.projectId })
.returns({
toArray: sinon.stub().yields(
null,
toArray: sinon.stub().resolves(
this.docIds.map(id => ({
_id: id,
}))
),
})
this.MongoManager.destroyProject(this.projectId, done)
await this.MongoManager.promises.destroyProject(this.projectId)
})
it('should destroy all docs', function () {
@ -340,10 +312,10 @@ describe('MongoManager', function () {
describe('getDocVersion', function () {
describe('when the doc exists', function () {
beforeEach(function () {
beforeEach(async function () {
this.doc = { version: (this.version = 42) }
this.db.docOps.findOne = sinon.stub().callsArgWith(2, null, this.doc)
this.MongoManager.getDocVersion(this.docId, this.callback)
this.db.docOps.findOne = sinon.stub().resolves(this.doc)
this.result = await this.MongoManager.promises.getDocVersion(this.docId)
})
it('should look for the doc in the database', function () {
@ -357,19 +329,19 @@ describe('MongoManager', function () {
.should.equal(true)
})
it('should call the callback with the version', function () {
this.callback.calledWith(null, this.version).should.equal(true)
it('should return the version', function () {
expect(this.result).to.equal(this.version)
})
})
describe("when the doc doesn't exist", function () {
beforeEach(function () {
this.db.docOps.findOne = sinon.stub().callsArgWith(2, null, null)
this.MongoManager.getDocVersion(this.docId, this.callback)
beforeEach(async function () {
this.db.docOps.findOne = sinon.stub().resolves(null)
this.result = await this.MongoManager.promises.getDocVersion(this.docId)
})
it('should call the callback with 0', function () {
this.callback.calledWith(null, 0).should.equal(true)
it('should return 0', function () {
expect(this.result).to.equal(0)
})
})
})
@ -379,37 +351,31 @@ describe('MongoManager', function () {
this.doc = { _id: new ObjectId(), name: 'mock-doc', rev: 1 }
})
it('should call the callback when the rev has not changed', function (done) {
this.db.docs.findOne = sinon.stub().callsArgWith(2, null, { rev: 1 })
this.MongoManager.checkRevUnchanged(this.doc, err => {
assert.isUndefined(err)
done()
})
it('should not error when the rev has not changed', async function () {
this.db.docs.findOne = sinon.stub().resolves({ rev: 1 })
await this.MongoManager.promises.checkRevUnchanged(this.doc)
})
it('should return an error when the rev has changed', function (done) {
this.db.docs.findOne = sinon.stub().callsArgWith(2, null, { rev: 2 })
this.MongoManager.checkRevUnchanged(this.doc, err => {
err.should.be.instanceof(Errors.DocModifiedError)
done()
})
it('should return an error when the rev has changed', async function () {
this.db.docs.findOne = sinon.stub().resolves({ rev: 2 })
await expect(
this.MongoManager.promises.checkRevUnchanged(this.doc)
).to.be.rejectedWith(Errors.DocModifiedError)
})
it('should return a value error if incoming rev is NaN', function (done) {
this.db.docs.findOne = sinon.stub().callsArgWith(2, null, { rev: 2 })
it('should return a value error if incoming rev is NaN', async function () {
this.db.docs.findOne = sinon.stub().resolves({ rev: 2 })
this.doc = { _id: new ObjectId(), name: 'mock-doc', rev: NaN }
this.MongoManager.checkRevUnchanged(this.doc, err => {
err.should.be.instanceof(Errors.DocRevValueError)
done()
})
await expect(
this.MongoManager.promises.checkRevUnchanged(this.doc)
).to.be.rejectedWith(Errors.DocRevValueError)
})
it('should return a value error if checked doc rev is NaN', function (done) {
this.db.docs.findOne = sinon.stub().callsArgWith(2, null, { rev: NaN })
this.MongoManager.checkRevUnchanged(this.doc, err => {
err.should.be.instanceof(Errors.DocRevValueError)
done()
})
it('should return a value error if checked doc rev is NaN', async function () {
this.db.docs.findOne = sinon.stub().resolves({ rev: NaN })
await expect(
this.MongoManager.promises.checkRevUnchanged(this.doc)
).to.be.rejectedWith(Errors.DocRevValueError)
})
})
@ -423,12 +389,11 @@ describe('MongoManager', function () {
})
describe('complete doc', function () {
beforeEach(function (done) {
this.MongoManager.restoreArchivedDoc(
beforeEach(async function () {
await this.MongoManager.promises.restoreArchivedDoc(
this.projectId,
this.docId,
this.archivedDoc,
done
this.archivedDoc
)
})
@ -453,13 +418,12 @@ describe('MongoManager', function () {
})
describe('without ranges', function () {
beforeEach(function (done) {
beforeEach(async function () {
delete this.archivedDoc.ranges
this.MongoManager.restoreArchivedDoc(
await this.MongoManager.promises.restoreArchivedDoc(
this.projectId,
this.docId,
this.archivedDoc,
done
this.archivedDoc
)
})
@ -484,17 +448,15 @@ describe('MongoManager', function () {
})
describe("when the update doesn't succeed", function () {
it('throws a DocRevValueError', function (done) {
this.db.docs.updateOne.yields(null, { matchedCount: 0 })
this.MongoManager.restoreArchivedDoc(
this.projectId,
this.docId,
this.archivedDoc,
err => {
expect(err).to.be.instanceof(Errors.DocRevValueError)
done()
}
)
it('throws a DocRevValueError', async function () {
this.db.docs.updateOne.resolves({ matchedCount: 0 })
await expect(
this.MongoManager.promises.restoreArchivedDoc(
this.projectId,
this.docId,
this.archivedDoc
)
).to.be.rejectedWith(Errors.DocRevValueError)
})
})
})