Merge pull request #7581 from overleaf/em-docstore-decaf

Decaf cleanup in docstore

GitOrigin-RevId: 84553cec7f184d567dc796c4016d6a412fb8db99
This commit is contained in:
Eric Mc Sween 2022-04-19 08:28:47 -04:00 committed by Copybot
parent e0d5cf4b42
commit 552d6d4baa
4 changed files with 643 additions and 709 deletions

View file

@ -1,329 +1,296 @@
/* eslint-disable
camelcase,
valid-typeof,
*/
// TODO: This file was created by bulk-decaffeinate.
// Fix any style issues and re-enable lint.
/*
* decaffeinate suggestions:
* DS101: Remove unnecessary use of Array.from
* DS102: Remove unnecessary code created because of implicit returns
* DS207: Consider shorter variations of null checks
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
let HttpController
const DocManager = require('./DocManager') const DocManager = require('./DocManager')
const logger = require('@overleaf/logger') const logger = require('@overleaf/logger')
const DocArchive = require('./DocArchiveManager') const DocArchive = require('./DocArchiveManager')
const HealthChecker = require('./HealthChecker') const HealthChecker = require('./HealthChecker')
const Settings = require('@overleaf/settings') const Settings = require('@overleaf/settings')
module.exports = HttpController = { function getDoc(req, res, next) {
getDoc(req, res, next) { const { doc_id: docId, project_id: projectId } = req.params
if (next == null) { const includeDeleted = req.query.include_deleted === 'true'
next = function () {} logger.log({ projectId, docId }, 'getting doc')
DocManager.getFullDoc(projectId, docId, function (error, doc) {
if (error) {
return next(error)
} }
const { project_id } = req.params logger.log({ docId, projectId }, 'got doc')
const { doc_id } = req.params if (doc == null) {
const include_deleted = res.sendStatus(404)
(req.query != null ? req.query.include_deleted : undefined) === 'true' } else if (doc.deleted && !includeDeleted) {
logger.log({ project_id, doc_id }, 'getting doc') res.sendStatus(404)
return DocManager.getFullDoc(project_id, doc_id, function (error, doc) { } else {
if (error != null) { res.json(_buildDocView(doc))
return next(error)
}
logger.log({ doc_id, project_id }, 'got doc')
if (doc == null) {
return res.sendStatus(404)
} else if (doc.deleted && !include_deleted) {
return res.sendStatus(404)
} else {
return res.json(HttpController._buildDocView(doc))
}
})
},
peekDoc(req, res, next) {
const { project_id } = req.params
const { doc_id } = req.params
logger.log({ project_id, doc_id }, 'peeking doc')
DocManager.peekDoc(project_id, doc_id, function (error, doc) {
if (error) {
return next(error)
}
if (doc == null) {
return res.sendStatus(404)
} else {
res.setHeader('x-doc-status', doc.inS3 ? 'archived' : 'active')
return res.json(HttpController._buildDocView(doc))
}
})
},
isDocDeleted(req, res, next) {
const { doc_id: docId, project_id: projectId } = req.params
DocManager.isDocDeleted(projectId, docId, function (error, deleted) {
if (error) {
return next(error)
}
res.json({ deleted })
})
},
getRawDoc(req, res, next) {
if (next == null) {
next = function () {}
} }
const { project_id } = req.params })
const { doc_id } = req.params }
logger.log({ project_id, doc_id }, 'getting raw doc')
return DocManager.getDocLines(project_id, doc_id, function (error, doc) { function peekDoc(req, res, next) {
if (error != null) { const { doc_id: docId, project_id: projectId } = req.params
return next(error) logger.log({ projectId, docId }, 'peeking doc')
} DocManager.peekDoc(projectId, docId, function (error, doc) {
if (doc == null) { if (error) {
return res.sendStatus(404) return next(error)
} else { }
res.setHeader('content-type', 'text/plain') if (doc == null) {
return res.send(HttpController._buildRawDocView(doc)) res.sendStatus(404)
} } else {
}) res.setHeader('x-doc-status', doc.inS3 ? 'archived' : 'active')
}, res.json(_buildDocView(doc))
}
getAllDocs(req, res, next) { })
if (next == null) { }
next = function () {}
} function isDocDeleted(req, res, next) {
const { project_id } = req.params const { doc_id: docId, project_id: projectId } = req.params
logger.log({ project_id }, 'getting all docs') DocManager.isDocDeleted(projectId, docId, function (error, deleted) {
return DocManager.getAllNonDeletedDocs( if (error) {
project_id, return next(error)
{ lines: true, rev: true }, }
function (error, docs) { res.json({ deleted })
if (docs == null) { })
docs = [] }
}
if (error != null) { function getRawDoc(req, res, next) {
return next(error) const { doc_id: docId, project_id: projectId } = req.params
} logger.log({ projectId, docId }, 'getting raw doc')
return res.json(HttpController._buildDocsArrayView(project_id, docs)) DocManager.getDocLines(projectId, docId, function (error, doc) {
} if (error) {
) return next(error)
}, }
if (doc == null) {
getAllDeletedDocs(req, res, next) { res.sendStatus(404)
const { project_id } = req.params } else {
logger.log({ project_id }, 'getting all deleted docs') res.setHeader('content-type', 'text/plain')
DocManager.getAllDeletedDocs( res.send(_buildRawDocView(doc))
project_id, }
{ name: true, deletedAt: true }, })
function (error, docs) { }
if (error) {
return next(error) function getAllDocs(req, res, next) {
} const { project_id: projectId } = req.params
res.json( logger.log({ projectId }, 'getting all docs')
docs.map(doc => { DocManager.getAllNonDeletedDocs(
return { projectId,
_id: doc._id.toString(), { lines: true, rev: true },
name: doc.name, function (error, docs) {
deletedAt: doc.deletedAt, if (docs == null) {
} docs = []
}) }
) if (error) {
} return next(error)
) }
}, res.json(_buildDocsArrayView(projectId, docs))
}
getAllRanges(req, res, next) { )
if (next == null) { }
next = function () {}
} function getAllDeletedDocs(req, res, next) {
const { project_id } = req.params const { project_id: projectId } = req.params
logger.log({ project_id }, 'getting all ranges') logger.log({ projectId }, 'getting all deleted docs')
return DocManager.getAllNonDeletedDocs( DocManager.getAllDeletedDocs(
project_id, projectId,
{ ranges: true }, { name: true, deletedAt: true },
function (error, docs) { function (error, docs) {
if (docs == null) { if (error) {
docs = [] return next(error)
} }
if (error != null) { res.json(
return next(error) docs.map(doc => ({
} _id: doc._id.toString(),
return res.json(HttpController._buildDocsArrayView(project_id, docs)) name: doc.name,
} deletedAt: doc.deletedAt,
) }))
}, )
}
updateDoc(req, res, next) { )
if (next == null) { }
next = function () {}
} function getAllRanges(req, res, next) {
const { project_id } = req.params const { project_id: projectId } = req.params
const { doc_id } = req.params logger.log({ projectId }, 'getting all ranges')
const lines = req.body != null ? req.body.lines : undefined DocManager.getAllNonDeletedDocs(
const version = req.body != null ? req.body.version : undefined projectId,
const ranges = req.body != null ? req.body.ranges : undefined { ranges: true },
function (error, docs) {
if (lines == null || !(lines instanceof Array)) { if (docs == null) {
logger.error({ project_id, doc_id }, 'no doc lines provided') docs = []
res.sendStatus(400) // Bad Request }
return if (error) {
} return next(error)
}
if (version == null || typeof version === !'number') { res.json(_buildDocsArrayView(projectId, docs))
logger.error({ project_id, doc_id }, 'no doc version provided') }
res.sendStatus(400) // Bad Request )
return }
}
function updateDoc(req, res, next) {
if (ranges == null) { const { doc_id: docId, project_id: projectId } = req.params
logger.error({ project_id, doc_id }, 'no doc ranges provided') const lines = req.body?.lines
res.sendStatus(400) // Bad Request const version = req.body?.version
return const ranges = req.body?.ranges
}
if (lines == null || !(lines instanceof Array)) {
const bodyLength = lines.reduce((len, line) => line.length + len, 0) logger.error({ projectId, docId }, 'no doc lines provided')
if (bodyLength > Settings.max_doc_length) { res.sendStatus(400) // Bad Request
logger.error( return
{ project_id, doc_id, bodyLength }, }
'document body too large'
) if (version == null || typeof version !== 'number') {
res.status(413).send('document body too large') logger.error({ projectId, docId }, 'no doc version provided')
return res.sendStatus(400) // Bad Request
} return
}
logger.log({ project_id, doc_id }, 'got http request to update doc')
return DocManager.updateDoc( if (ranges == null) {
project_id, logger.error({ projectId, docId }, 'no doc ranges provided')
doc_id, res.sendStatus(400) // Bad Request
lines, return
version, }
ranges,
function (error, modified, rev) { const bodyLength = lines.reduce((len, line) => line.length + len, 0)
if (error != null) { if (bodyLength > Settings.max_doc_length) {
return next(error) logger.error({ projectId, docId, bodyLength }, 'document body too large')
} res.status(413).send('document body too large')
return res.json({ return
modified, }
rev,
}) logger.log({ projectId, docId }, 'got http request to update doc')
} DocManager.updateDoc(
) projectId,
}, docId,
lines,
patchDoc(req, res, next) { version,
const { project_id, doc_id } = req.params ranges,
logger.log({ project_id, doc_id }, 'patching doc') function (error, modified, rev) {
if (error) {
const allowedFields = ['deleted', 'deletedAt', 'name'] return next(error)
const meta = {} }
Object.entries(req.body).forEach(([field, value]) => { res.json({
if (allowedFields.includes(field)) { modified,
meta[field] = value rev,
} else { })
logger.fatal({ field }, 'joi validation for pathDoc is broken') }
} )
}) }
DocManager.patchDoc(project_id, doc_id, meta, function (error) {
if (error) { function patchDoc(req, res, next) {
return next(error) const { doc_id: docId, project_id: projectId } = req.params
} logger.log({ projectId, docId }, 'patching doc')
res.sendStatus(204)
}) const allowedFields = ['deleted', 'deletedAt', 'name']
}, const meta = {}
Object.entries(req.body).forEach(([field, value]) => {
_buildDocView(doc) { if (allowedFields.includes(field)) {
const doc_view = { _id: doc._id != null ? doc._id.toString() : undefined } meta[field] = value
for (const attribute of ['lines', 'rev', 'version', 'ranges', 'deleted']) { } else {
if (doc[attribute] != null) { logger.fatal({ field }, 'joi validation for pathDoc is broken')
doc_view[attribute] = doc[attribute] }
} })
} DocManager.patchDoc(projectId, docId, meta, function (error) {
return doc_view if (error) {
}, return next(error)
}
_buildRawDocView(doc) { res.sendStatus(204)
return ((doc != null ? doc.lines : undefined) || []).join('\n') })
}, }
_buildDocsArrayView(project_id, docs) { function _buildDocView(doc) {
const docViews = [] const docView = { _id: doc._id?.toString() }
for (const doc of Array.from(docs)) { for (const attribute of ['lines', 'rev', 'version', 'ranges', 'deleted']) {
if (doc != null) { if (doc[attribute] != null) {
// There can end up being null docs for some reason :( (probably a race condition) docView[attribute] = doc[attribute]
docViews.push(HttpController._buildDocView(doc)) }
} else { }
logger.error( return docView
{ err: new Error('null doc'), project_id }, }
'encountered null doc'
) function _buildRawDocView(doc) {
} return (doc?.lines ?? []).join('\n')
} }
return docViews
}, function _buildDocsArrayView(projectId, docs) {
const docViews = []
archiveAllDocs(req, res, next) { for (const doc of docs) {
if (next == null) { if (doc != null) {
next = function () {} // There can end up being null docs for some reason :( (probably a race condition)
} docViews.push(_buildDocView(doc))
const { project_id } = req.params } else {
logger.log({ project_id }, 'archiving all docs') logger.error(
return DocArchive.archiveAllDocs(project_id, function (error) { { err: new Error('null doc'), projectId },
if (error != null) { 'encountered null doc'
return next(error) )
} }
return res.sendStatus(204) }
}) return docViews
}, }
archiveDoc(req, res, next) { function archiveAllDocs(req, res, next) {
const { project_id, doc_id } = req.params const { project_id: projectId } = req.params
logger.log({ project_id, doc_id }, 'archiving a doc') logger.log({ projectId }, 'archiving all docs')
DocArchive.archiveDocById(project_id, doc_id, function (error) { DocArchive.archiveAllDocs(projectId, function (error) {
if (error) { if (error) {
return next(error) return next(error)
} }
res.sendStatus(204) res.sendStatus(204)
}) })
}, }
unArchiveAllDocs(req, res, next) { function archiveDoc(req, res, next) {
if (next == null) { const { doc_id: docId, project_id: projectId } = req.params
next = function () {} logger.log({ projectId, docId }, 'archiving a doc')
} DocArchive.archiveDocById(projectId, docId, function (error) {
const { project_id } = req.params if (error) {
logger.log({ project_id }, 'unarchiving all docs') return next(error)
return DocArchive.unArchiveAllDocs(project_id, function (error) { }
if (error != null) { res.sendStatus(204)
return next(error) })
} }
return res.sendStatus(200)
}) function unArchiveAllDocs(req, res, next) {
}, const { project_id: projectId } = req.params
logger.log({ projectId }, 'unarchiving all docs')
destroyAllDocs(req, res, next) { DocArchive.unArchiveAllDocs(projectId, function (error) {
if (next == null) { if (error) {
next = function () {} return next(error)
} }
const { project_id } = req.params res.sendStatus(200)
logger.log({ project_id }, 'destroying all docs') })
return DocArchive.destroyAllDocs(project_id, function (error) { }
if (error != null) {
return next(error) function destroyAllDocs(req, res, next) {
} const { project_id: projectId } = req.params
return res.sendStatus(204) logger.log({ projectId }, 'destroying all docs')
}) DocArchive.destroyAllDocs(projectId, function (error) {
}, if (error) {
return next(error)
healthCheck(req, res) { }
return HealthChecker.check(function (err) { res.sendStatus(204)
if (err != null) { })
logger.err({ err }, 'error performing health check') }
return res.sendStatus(500)
} else { function healthCheck(req, res) {
return res.sendStatus(200) HealthChecker.check(function (err) {
} if (err) {
}) logger.err({ err }, 'error performing health check')
}, res.sendStatus(500)
} else {
res.sendStatus(200)
}
})
}
module.exports = {
getDoc,
peekDoc,
isDocDeleted,
getRawDoc,
getAllDocs,
getAllDeletedDocs,
getAllRanges,
updateDoc,
patchDoc,
archiveAllDocs,
archiveDoc,
unArchiveAllDocs,
destroyAllDocs,
healthCheck,
} }

View file

@ -1,15 +1,3 @@
/* eslint-disable
camelcase,
*/
// TODO: This file was created by bulk-decaffeinate.
// Fix any style issues and re-enable lint.
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* DS207: Consider shorter variations of null checks
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
let MongoManager
const { db, ObjectId } = require('./mongodb') const { db, ObjectId } = require('./mongodb')
const logger = require('@overleaf/logger') const logger = require('@overleaf/logger')
const metrics = require('@overleaf/metrics') const metrics = require('@overleaf/metrics')
@ -17,239 +5,243 @@ const Settings = require('@overleaf/settings')
const Errors = require('./Errors') const Errors = require('./Errors')
const { promisify } = require('util') const { promisify } = require('util')
module.exports = MongoManager = { function findDoc(projectId, docId, filter, callback) {
findDoc(project_id, doc_id, filter, callback) { db.docs.findOne(
if (callback == null) { {
callback = function () {} _id: ObjectId(docId.toString()),
} project_id: ObjectId(projectId.toString()),
db.docs.findOne( },
{
projection: filter,
},
callback
)
}
function getProjectsDeletedDocs(projectId, filter, callback) {
db.docs
.find(
{ {
_id: ObjectId(doc_id.toString()), project_id: ObjectId(projectId.toString()),
project_id: ObjectId(project_id.toString()), deleted: true,
}, },
{ {
projection: filter, projection: filter,
}, sort: { deletedAt: -1 },
callback limit: Settings.max_deleted_docs,
)
},
getProjectsDeletedDocs(project_id, filter, callback) {
db.docs
.find(
{
project_id: ObjectId(project_id.toString()),
deleted: true,
},
{
projection: filter,
sort: { deletedAt: -1 },
limit: Settings.max_deleted_docs,
}
)
.toArray(callback)
},
getProjectsDocs(project_id, options, filter, callback) {
const query = { project_id: ObjectId(project_id.toString()) }
if (!options.include_deleted) {
query.deleted = { $ne: true }
}
const queryOptions = {
projection: filter,
}
if (options.limit) {
queryOptions.limit = options.limit
}
db.docs.find(query, queryOptions).toArray(callback)
},
getArchivedProjectDocs(project_id, maxResults, callback) {
const query = {
project_id: ObjectId(project_id.toString()),
inS3: true,
}
db.docs
.find(query, { projection: { _id: 1 }, limit: maxResults })
.toArray(callback)
},
getNonArchivedProjectDocs(project_id, maxResults, callback) {
const query = {
project_id: ObjectId(project_id.toString()),
inS3: { $ne: true },
}
db.docs.find(query, { limit: maxResults }).toArray(callback)
},
getNonDeletedArchivedProjectDocs(project_id, maxResults, callback) {
const query = {
project_id: ObjectId(project_id.toString()),
deleted: { $ne: true },
inS3: true,
}
db.docs
.find(query, { projection: { _id: 1 }, limit: maxResults })
.toArray(callback)
},
upsertIntoDocCollection(project_id, doc_id, updates, callback) {
const update = {
$set: updates,
$inc: {
rev: 1,
},
$unset: {
inS3: true,
},
}
update.$set.project_id = ObjectId(project_id)
db.docs.updateOne(
{ _id: ObjectId(doc_id) },
update,
{ upsert: true },
callback
)
},
patchDoc(project_id, doc_id, meta, callback) {
db.docs.updateOne(
{
_id: ObjectId(doc_id),
project_id: ObjectId(project_id),
},
{ $set: meta },
callback
)
},
markDocAsArchived(doc_id, rev, callback) {
const update = {
$set: {},
$unset: {},
}
update.$set.inS3 = true
update.$unset.lines = true
update.$unset.ranges = true
const query = {
_id: doc_id,
rev,
}
db.docs.updateOne(query, update, callback)
},
getDocVersion(doc_id, callback) {
if (callback == null) {
callback = function () {}
}
db.docOps.findOne(
{
doc_id: ObjectId(doc_id),
},
{
projection: {
version: 1,
},
},
function (error, doc) {
if (error != null) {
return callback(error)
}
callback(null, (doc && doc.version) || 0)
} }
) )
}, .toArray(callback)
}
setDocVersion(doc_id, version, callback) { function getProjectsDocs(projectId, options, filter, callback) {
if (callback == null) { const query = { project_id: ObjectId(projectId.toString()) }
callback = function () {} if (!options.include_deleted) {
} query.deleted = { $ne: true }
db.docOps.updateOne( }
{ const queryOptions = {
doc_id: ObjectId(doc_id), projection: filter,
}, }
{ if (options.limit) {
$set: { version }, queryOptions.limit = options.limit
}, }
{ db.docs.find(query, queryOptions).toArray(callback)
upsert: true, }
},
callback
)
},
getDocRev(doc_id, callback) { function getArchivedProjectDocs(projectId, maxResults, callback) {
db.docs.findOne( const query = {
{ project_id: ObjectId(projectId.toString()),
_id: ObjectId(doc_id.toString()), inS3: true,
}
db.docs
.find(query, { projection: { _id: 1 }, limit: maxResults })
.toArray(callback)
}
function getNonArchivedProjectDocs(projectId, maxResults, callback) {
const query = {
project_id: ObjectId(projectId.toString()),
inS3: { $ne: true },
}
db.docs.find(query, { limit: maxResults }).toArray(callback)
}
function getNonDeletedArchivedProjectDocs(projectId, maxResults, callback) {
const query = {
project_id: ObjectId(projectId.toString()),
deleted: { $ne: true },
inS3: true,
}
db.docs
.find(query, { projection: { _id: 1 }, limit: maxResults })
.toArray(callback)
}
function upsertIntoDocCollection(projectId, docId, updates, callback) {
const update = {
$set: updates,
$inc: {
rev: 1,
},
$unset: {
inS3: true,
},
}
update.$set.project_id = ObjectId(projectId)
db.docs.updateOne(
{ _id: ObjectId(docId) },
update,
{ upsert: true },
callback
)
}
function patchDoc(projectId, docId, meta, callback) {
db.docs.updateOne(
{
_id: ObjectId(docId),
project_id: ObjectId(projectId),
},
{ $set: meta },
callback
)
}
function markDocAsArchived(docId, rev, callback) {
const update = {
$set: {},
$unset: {},
}
update.$set.inS3 = true
update.$unset.lines = true
update.$unset.ranges = true
const query = {
_id: docId,
rev,
}
db.docs.updateOne(query, update, callback)
}
function getDocVersion(docId, callback) {
db.docOps.findOne(
{
doc_id: ObjectId(docId),
},
{
projection: {
version: 1,
}, },
{ },
projection: { rev: 1 }, function (error, doc) {
}, if (error) {
function (err, doc) { return callback(error)
if (err != null) {
return callback(err)
}
callback(null, doc && doc.rev)
} }
) callback(null, (doc && doc.version) || 0)
}, }
)
}
// Helper method to support optimistic locking. Call the provided method for function setDocVersion(docId, version, callback) {
// an existing doc and return the result if the rev in mongo is unchanged when db.docOps.updateOne(
// checked afterwards. If the rev has changed, return a DocModifiedError. {
withRevCheck(doc, method, callback) { doc_id: ObjectId(docId),
method(doc._id, function (err, result) { },
{
$set: { version },
},
{
upsert: true,
},
callback
)
}
function getDocRev(docId, callback) {
db.docs.findOne(
{
_id: ObjectId(docId.toString()),
},
{
projection: { rev: 1 },
},
function (err, doc) {
if (err) {
return callback(err)
}
callback(null, doc && doc.rev)
}
)
}
// Helper method to support optimistic locking. Call the provided method for
// an existing doc and return the result if the rev in mongo is unchanged when
// checked afterwards. If the rev has changed, return a DocModifiedError.
function withRevCheck(doc, method, callback) {
method(doc._id, function (err, result) {
if (err) return callback(err)
getDocRev(doc._id, function (err, currentRev) {
if (err) return callback(err) if (err) return callback(err)
MongoManager.getDocRev(doc._id, function (err, currentRev) { if (isNaN(currentRev) || isNaN(doc.rev)) {
if (err) return callback(err) return callback(
if (isNaN(currentRev) || isNaN(doc.rev)) { new Errors.DocRevValueError('doc rev is NaN', {
return callback( doc_id: doc._id,
new Errors.DocRevValueError('doc rev is NaN', { rev: doc.rev,
doc_id: doc._id, currentRev,
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,
})
)
}
return callback(null, result)
})
})
},
destroyDoc(doc_id, callback) {
db.docs.deleteOne(
{
_id: ObjectId(doc_id),
},
function (err) {
if (err != null) {
return callback(err)
}
db.docOps.deleteOne(
{
doc_id: ObjectId(doc_id),
},
callback
) )
} }
) if (doc.rev !== currentRev) {
}, return callback(
new Errors.DocModifiedError('doc rev has changed', {
doc_id: doc._id,
rev: doc.rev,
currentRev,
})
)
}
callback(null, result)
})
})
} }
const methods = Object.getOwnPropertyNames(MongoManager) function destroyDoc(docId, callback) {
db.docs.deleteOne(
{
_id: ObjectId(docId),
},
function (err) {
if (err) {
return callback(err)
}
db.docOps.deleteOne(
{
doc_id: ObjectId(docId),
},
callback
)
}
)
}
module.exports = {
findDoc,
getProjectsDeletedDocs,
getProjectsDocs,
getArchivedProjectDocs,
getNonArchivedProjectDocs,
getNonDeletedArchivedProjectDocs,
upsertIntoDocCollection,
patchDoc,
markDocAsArchived,
getDocVersion,
setDocVersion,
withRevCheck,
destroyDoc,
}
const methods = Object.getOwnPropertyNames(module.exports)
module.exports.promises = {} module.exports.promises = {}
for (const method of methods) { for (const method of methods) {
metrics.timeAsyncMethod(MongoManager, method, 'mongo.MongoManager', logger) metrics.timeAsyncMethod(module.exports, method, 'mongo.MongoManager', logger)
module.exports.promises[method] = promisify(module.exports[method]) module.exports.promises[method] = promisify(module.exports[method])
} }

View file

@ -1,14 +1,3 @@
/* eslint-disable
no-return-assign,
no-unused-vars,
*/
// TODO: This file was created by bulk-decaffeinate.
// Fix any style issues and re-enable lint.
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
const SandboxedModule = require('sandboxed-module') const SandboxedModule = require('sandboxed-module')
const sinon = require('sinon') const sinon = require('sinon')
const { assert, expect } = require('chai') const { assert, expect } = require('chai')
@ -40,46 +29,46 @@ describe('HttpController', function () {
this.res.status = sinon.stub().returns(this.res) this.res.status = sinon.stub().returns(this.res)
this.req = { query: {} } this.req = { query: {} }
this.next = sinon.stub() this.next = sinon.stub()
this.project_id = 'mock-project-id' this.projectId = 'mock-project-id'
this.doc_id = 'mock-doc-id' this.docId = 'mock-doc-id'
this.doc = { this.doc = {
_id: this.doc_id, _id: this.docId,
lines: ['mock', 'lines', ' here', '', '', ' spaces '], lines: ['mock', 'lines', ' here', '', '', ' spaces '],
version: 42, version: 42,
rev: 5, rev: 5,
} }
return (this.deletedDoc = { this.deletedDoc = {
deleted: true, deleted: true,
_id: this.doc_id, _id: this.docId,
lines: ['mock', 'lines', ' here', '', '', ' spaces '], lines: ['mock', 'lines', ' here', '', '', ' spaces '],
version: 42, version: 42,
rev: 5, rev: 5,
}) }
}) })
describe('getDoc', function () { describe('getDoc', function () {
describe('without deleted docs', function () { describe('without deleted docs', function () {
beforeEach(function () { beforeEach(function () {
this.req.params = { this.req.params = {
project_id: this.project_id, project_id: this.projectId,
doc_id: this.doc_id, doc_id: this.docId,
} }
this.DocManager.getFullDoc = sinon this.DocManager.getFullDoc = sinon
.stub() .stub()
.callsArgWith(2, null, this.doc) .callsArgWith(2, null, this.doc)
return this.HttpController.getDoc(this.req, this.res, this.next) this.HttpController.getDoc(this.req, this.res, this.next)
}) })
it('should get the document with the version (including deleted)', function () { it('should get the document with the version (including deleted)', function () {
return this.DocManager.getFullDoc this.DocManager.getFullDoc
.calledWith(this.project_id, this.doc_id) .calledWith(this.projectId, this.docId)
.should.equal(true) .should.equal(true)
}) })
return it('should return the doc as JSON', function () { it('should return the doc as JSON', function () {
return this.res.json this.res.json
.calledWith({ .calledWith({
_id: this.doc_id, _id: this.docId,
lines: this.doc.lines, lines: this.doc.lines,
rev: this.doc.rev, rev: this.doc.rev,
version: this.doc.version, version: this.doc.version,
@ -88,35 +77,35 @@ describe('HttpController', function () {
}) })
}) })
return describe('which is deleted', function () { describe('which is deleted', function () {
beforeEach(function () { beforeEach(function () {
this.req.params = { this.req.params = {
project_id: this.project_id, project_id: this.projectId,
doc_id: this.doc_id, doc_id: this.docId,
} }
return (this.DocManager.getFullDoc = sinon this.DocManager.getFullDoc = sinon
.stub() .stub()
.callsArgWith(2, null, this.deletedDoc)) .callsArgWith(2, null, this.deletedDoc)
}) })
it('should get the doc from the doc manager', function () { it('should get the doc from the doc manager', function () {
this.HttpController.getDoc(this.req, this.res, this.next) this.HttpController.getDoc(this.req, this.res, this.next)
return this.DocManager.getFullDoc this.DocManager.getFullDoc
.calledWith(this.project_id, this.doc_id) .calledWith(this.projectId, this.docId)
.should.equal(true) .should.equal(true)
}) })
it('should return 404 if the query string delete is not set ', function () { it('should return 404 if the query string delete is not set ', function () {
this.HttpController.getDoc(this.req, this.res, this.next) this.HttpController.getDoc(this.req, this.res, this.next)
return this.res.sendStatus.calledWith(404).should.equal(true) this.res.sendStatus.calledWith(404).should.equal(true)
}) })
return it('should return the doc as JSON if include_deleted is set to true', function () { it('should return the doc as JSON if include_deleted is set to true', function () {
this.req.query.include_deleted = 'true' this.req.query.include_deleted = 'true'
this.HttpController.getDoc(this.req, this.res, this.next) this.HttpController.getDoc(this.req, this.res, this.next)
return this.res.json this.res.json
.calledWith({ .calledWith({
_id: this.doc_id, _id: this.docId,
lines: this.doc.lines, lines: this.doc.lines,
rev: this.doc.rev, rev: this.doc.rev,
deleted: true, deleted: true,
@ -130,27 +119,27 @@ describe('HttpController', function () {
describe('getRawDoc', function () { describe('getRawDoc', function () {
beforeEach(function () { beforeEach(function () {
this.req.params = { this.req.params = {
project_id: this.project_id, project_id: this.projectId,
doc_id: this.doc_id, doc_id: this.docId,
} }
this.DocManager.getDocLines = sinon.stub().callsArgWith(2, null, this.doc) this.DocManager.getDocLines = sinon.stub().callsArgWith(2, null, this.doc)
return this.HttpController.getRawDoc(this.req, this.res, this.next) this.HttpController.getRawDoc(this.req, this.res, this.next)
}) })
it('should get the document without the version', function () { it('should get the document without the version', function () {
return this.DocManager.getDocLines this.DocManager.getDocLines
.calledWith(this.project_id, this.doc_id) .calledWith(this.projectId, this.docId)
.should.equal(true) .should.equal(true)
}) })
it('should set the content type header', function () { it('should set the content type header', function () {
return this.res.setHeader this.res.setHeader
.calledWith('content-type', 'text/plain') .calledWith('content-type', 'text/plain')
.should.equal(true) .should.equal(true)
}) })
return it('should send the raw version of the doc', function () { it('should send the raw version of the doc', function () {
return assert.deepEqual( assert.deepEqual(
this.res.send.args[0][0], this.res.send.args[0][0],
`${this.doc.lines[0]}\n${this.doc.lines[1]}\n${this.doc.lines[2]}\n${this.doc.lines[3]}\n${this.doc.lines[4]}\n${this.doc.lines[5]}` `${this.doc.lines[0]}\n${this.doc.lines[1]}\n${this.doc.lines[2]}\n${this.doc.lines[3]}\n${this.doc.lines[4]}\n${this.doc.lines[5]}`
) )
@ -160,7 +149,7 @@ describe('HttpController', function () {
describe('getAllDocs', function () { describe('getAllDocs', function () {
describe('normally', function () { describe('normally', function () {
beforeEach(function () { beforeEach(function () {
this.req.params = { project_id: this.project_id } this.req.params = { project_id: this.projectId }
this.docs = [ this.docs = [
{ {
_id: ObjectId(), _id: ObjectId(),
@ -176,17 +165,17 @@ describe('HttpController', function () {
this.DocManager.getAllNonDeletedDocs = sinon this.DocManager.getAllNonDeletedDocs = sinon
.stub() .stub()
.callsArgWith(2, null, this.docs) .callsArgWith(2, null, this.docs)
return this.HttpController.getAllDocs(this.req, this.res, this.next) this.HttpController.getAllDocs(this.req, this.res, this.next)
}) })
it('should get all the (non-deleted) docs', function () { it('should get all the (non-deleted) docs', function () {
return this.DocManager.getAllNonDeletedDocs this.DocManager.getAllNonDeletedDocs
.calledWith(this.project_id, { lines: true, rev: true }) .calledWith(this.projectId, { lines: true, rev: true })
.should.equal(true) .should.equal(true)
}) })
return it('should return the doc as JSON', function () { it('should return the doc as JSON', function () {
return this.res.json this.res.json
.calledWith([ .calledWith([
{ {
_id: this.docs[0]._id.toString(), _id: this.docs[0]._id.toString(),
@ -203,9 +192,9 @@ describe('HttpController', function () {
}) })
}) })
return describe('with a null doc', function () { describe('with a null doc', function () {
beforeEach(function () { beforeEach(function () {
this.req.params = { project_id: this.project_id } this.req.params = { project_id: this.projectId }
this.docs = [ this.docs = [
{ {
_id: ObjectId(), _id: ObjectId(),
@ -222,11 +211,11 @@ describe('HttpController', function () {
this.DocManager.getAllNonDeletedDocs = sinon this.DocManager.getAllNonDeletedDocs = sinon
.stub() .stub()
.callsArgWith(2, null, this.docs) .callsArgWith(2, null, this.docs)
return this.HttpController.getAllDocs(this.req, this.res, this.next) this.HttpController.getAllDocs(this.req, this.res, this.next)
}) })
it('should return the non null docs as JSON', function () { it('should return the non null docs as JSON', function () {
return this.res.json this.res.json
.calledWith([ .calledWith([
{ {
_id: this.docs[0]._id.toString(), _id: this.docs[0]._id.toString(),
@ -242,12 +231,12 @@ describe('HttpController', function () {
.should.equal(true) .should.equal(true)
}) })
return it('should log out an error', function () { it('should log out an error', function () {
return this.logger.error this.logger.error
.calledWith( .calledWith(
{ {
err: sinon.match.has('message', 'null doc'), err: sinon.match.has('message', 'null doc'),
project_id: this.project_id, projectId: this.projectId,
}, },
'encountered null doc' 'encountered null doc'
) )
@ -257,9 +246,9 @@ describe('HttpController', function () {
}) })
describe('getAllRanges', function () { describe('getAllRanges', function () {
return describe('normally', function () { describe('normally', function () {
beforeEach(function () { beforeEach(function () {
this.req.params = { project_id: this.project_id } this.req.params = { project_id: this.projectId }
this.docs = [ this.docs = [
{ {
_id: ObjectId(), _id: ObjectId(),
@ -273,17 +262,17 @@ describe('HttpController', function () {
this.DocManager.getAllNonDeletedDocs = sinon this.DocManager.getAllNonDeletedDocs = sinon
.stub() .stub()
.callsArgWith(2, null, this.docs) .callsArgWith(2, null, this.docs)
return this.HttpController.getAllRanges(this.req, this.res, this.next) this.HttpController.getAllRanges(this.req, this.res, this.next)
}) })
it('should get all the (non-deleted) doc ranges', function () { it('should get all the (non-deleted) doc ranges', function () {
return this.DocManager.getAllNonDeletedDocs this.DocManager.getAllNonDeletedDocs
.calledWith(this.project_id, { ranges: true }) .calledWith(this.projectId, { ranges: true })
.should.equal(true) .should.equal(true)
}) })
return it('should return the doc as JSON', function () { it('should return the doc as JSON', function () {
return this.res.json this.res.json
.calledWith([ .calledWith([
{ {
_id: this.docs[0]._id.toString(), _id: this.docs[0]._id.toString(),
@ -301,10 +290,10 @@ describe('HttpController', function () {
describe('updateDoc', function () { describe('updateDoc', function () {
beforeEach(function () { beforeEach(function () {
return (this.req.params = { this.req.params = {
project_id: this.project_id, project_id: this.projectId,
doc_id: this.doc_id, doc_id: this.docId,
}) }
}) })
describe('when the doc lines exist and were updated', function () { describe('when the doc lines exist and were updated', function () {
@ -317,14 +306,14 @@ describe('HttpController', function () {
this.DocManager.updateDoc = sinon this.DocManager.updateDoc = sinon
.stub() .stub()
.yields(null, true, (this.rev = 5)) .yields(null, true, (this.rev = 5))
return this.HttpController.updateDoc(this.req, this.res, this.next) this.HttpController.updateDoc(this.req, this.res, this.next)
}) })
it('should update the document', function () { it('should update the document', function () {
return this.DocManager.updateDoc this.DocManager.updateDoc
.calledWith( .calledWith(
this.project_id, this.projectId,
this.doc_id, this.docId,
this.lines, this.lines,
this.version, this.version,
this.ranges this.ranges
@ -332,8 +321,8 @@ describe('HttpController', function () {
.should.equal(true) .should.equal(true)
}) })
return it('should return a modified status', function () { it('should return a modified status', function () {
return this.res.json this.res.json
.calledWith({ modified: true, rev: this.rev }) .calledWith({ modified: true, rev: this.rev })
.should.equal(true) .should.equal(true)
}) })
@ -349,11 +338,11 @@ describe('HttpController', function () {
this.DocManager.updateDoc = sinon this.DocManager.updateDoc = sinon
.stub() .stub()
.yields(null, false, (this.rev = 5)) .yields(null, false, (this.rev = 5))
return this.HttpController.updateDoc(this.req, this.res, this.next) this.HttpController.updateDoc(this.req, this.res, this.next)
}) })
return it('should return a modified status', function () { it('should return a modified status', function () {
return this.res.json this.res.json
.calledWith({ modified: false, rev: this.rev }) .calledWith({ modified: false, rev: this.rev })
.should.equal(true) .should.equal(true)
}) })
@ -363,15 +352,15 @@ describe('HttpController', function () {
beforeEach(function () { beforeEach(function () {
this.req.body = { version: 42, ranges: {} } this.req.body = { version: 42, ranges: {} }
this.DocManager.updateDoc = sinon.stub().yields(null, false) this.DocManager.updateDoc = sinon.stub().yields(null, false)
return this.HttpController.updateDoc(this.req, this.res, this.next) this.HttpController.updateDoc(this.req, this.res, this.next)
}) })
it('should not update the document', function () { it('should not update the document', function () {
return this.DocManager.updateDoc.called.should.equal(false) this.DocManager.updateDoc.called.should.equal(false)
}) })
return it('should return a 400 (bad request) response', function () { it('should return a 400 (bad request) response', function () {
return this.res.sendStatus.calledWith(400).should.equal(true) this.res.sendStatus.calledWith(400).should.equal(true)
}) })
}) })
@ -379,15 +368,15 @@ describe('HttpController', function () {
beforeEach(function () { beforeEach(function () {
this.req.body = { version: 42, lines: ['hello world'] } this.req.body = { version: 42, lines: ['hello world'] }
this.DocManager.updateDoc = sinon.stub().yields(null, false) this.DocManager.updateDoc = sinon.stub().yields(null, false)
return this.HttpController.updateDoc(this.req, this.res, this.next) this.HttpController.updateDoc(this.req, this.res, this.next)
}) })
it('should not update the document', function () { it('should not update the document', function () {
return this.DocManager.updateDoc.called.should.equal(false) this.DocManager.updateDoc.called.should.equal(false)
}) })
return it('should return a 400 (bad request) response', function () { it('should return a 400 (bad request) response', function () {
return this.res.sendStatus.calledWith(400).should.equal(true) this.res.sendStatus.calledWith(400).should.equal(true)
}) })
}) })
@ -395,34 +384,34 @@ describe('HttpController', function () {
beforeEach(function () { beforeEach(function () {
this.req.body = { lines: ['foo'], version: 42 } this.req.body = { lines: ['foo'], version: 42 }
this.DocManager.updateDoc = sinon.stub().yields(null, false) this.DocManager.updateDoc = sinon.stub().yields(null, false)
return this.HttpController.updateDoc(this.req, this.res, this.next) this.HttpController.updateDoc(this.req, this.res, this.next)
}) })
it('should not update the document', function () { it('should not update the document', function () {
return this.DocManager.updateDoc.called.should.equal(false) this.DocManager.updateDoc.called.should.equal(false)
}) })
return it('should return a 400 (bad request) response', function () { it('should return a 400 (bad request) response', function () {
return this.res.sendStatus.calledWith(400).should.equal(true) this.res.sendStatus.calledWith(400).should.equal(true)
}) })
}) })
return describe('when the doc body is too large', function () { describe('when the doc body is too large', function () {
beforeEach(function () { beforeEach(function () {
this.req.body = { this.req.body = {
lines: (this.lines = Array(2049).fill('a'.repeat(1024))), lines: (this.lines = Array(2049).fill('a'.repeat(1024))),
version: (this.version = 42), version: (this.version = 42),
ranges: (this.ranges = { changes: 'mock' }), ranges: (this.ranges = { changes: 'mock' }),
} }
return this.HttpController.updateDoc(this.req, this.res, this.next) this.HttpController.updateDoc(this.req, this.res, this.next)
}) })
it('should return a 413 (too large) response', function () { it('should return a 413 (too large) response', function () {
return sinon.assert.calledWith(this.res.status, 413) sinon.assert.calledWith(this.res.status, 413)
}) })
return it('should report that the document body is too large', function () { it('should report that the document body is too large', function () {
return sinon.assert.calledWith(this.res.send, 'document body too large') sinon.assert.calledWith(this.res.send, 'document body too large')
}) })
}) })
}) })
@ -430,8 +419,8 @@ describe('HttpController', function () {
describe('patchDoc', function () { describe('patchDoc', function () {
beforeEach(function () { beforeEach(function () {
this.req.params = { this.req.params = {
project_id: this.project_id, project_id: this.projectId,
doc_id: this.doc_id, doc_id: this.docId,
} }
this.req.body = { name: 'foo.tex' } this.req.body = { name: 'foo.tex' }
this.DocManager.patchDoc = sinon.stub().yields(null) this.DocManager.patchDoc = sinon.stub().yields(null)
@ -440,8 +429,8 @@ describe('HttpController', function () {
it('should delete the document', function () { it('should delete the document', function () {
expect(this.DocManager.patchDoc).to.have.been.calledWith( expect(this.DocManager.patchDoc).to.have.been.calledWith(
this.project_id, this.projectId,
this.doc_id this.docId
) )
}) })
@ -466,8 +455,8 @@ describe('HttpController', function () {
it('should not pass the invalid field along', function () { it('should not pass the invalid field along', function () {
expect(this.DocManager.patchDoc).to.have.been.calledWith( expect(this.DocManager.patchDoc).to.have.been.calledWith(
this.project_id, this.projectId,
this.doc_id, this.docId,
{} {}
) )
}) })
@ -476,38 +465,38 @@ describe('HttpController', function () {
describe('archiveAllDocs', function () { describe('archiveAllDocs', function () {
beforeEach(function () { beforeEach(function () {
this.req.params = { project_id: this.project_id } this.req.params = { project_id: this.projectId }
this.DocArchiveManager.archiveAllDocs = sinon.stub().callsArg(1) this.DocArchiveManager.archiveAllDocs = sinon.stub().callsArg(1)
return this.HttpController.archiveAllDocs(this.req, this.res, this.next) this.HttpController.archiveAllDocs(this.req, this.res, this.next)
}) })
it('should archive the project', function () { it('should archive the project', function () {
return this.DocArchiveManager.archiveAllDocs this.DocArchiveManager.archiveAllDocs
.calledWith(this.project_id) .calledWith(this.projectId)
.should.equal(true) .should.equal(true)
}) })
return it('should return a 204 (No Content)', function () { it('should return a 204 (No Content)', function () {
return this.res.sendStatus.calledWith(204).should.equal(true) this.res.sendStatus.calledWith(204).should.equal(true)
}) })
}) })
return describe('destroyAllDocs', function () { describe('destroyAllDocs', function () {
beforeEach(function () { beforeEach(function () {
this.req.params = { project_id: this.project_id } this.req.params = { project_id: this.projectId }
this.DocArchiveManager.destroyAllDocs = sinon.stub().callsArg(1) this.DocArchiveManager.destroyAllDocs = sinon.stub().callsArg(1)
return this.HttpController.destroyAllDocs(this.req, this.res, this.next) this.HttpController.destroyAllDocs(this.req, this.res, this.next)
}) })
it('should destroy the docs', function () { it('should destroy the docs', function () {
return sinon.assert.calledWith( sinon.assert.calledWith(
this.DocArchiveManager.destroyAllDocs, this.DocArchiveManager.destroyAllDocs,
this.project_id this.projectId
) )
}) })
return it('should return 204', function () { it('should return 204', function () {
return sinon.assert.calledWith(this.res.sendStatus, 204) sinon.assert.calledWith(this.res.sendStatus, 204)
}) })
}) })
}) })

View file

@ -1,13 +1,3 @@
/* eslint-disable
no-return-assign,
*/
// TODO: This file was created by bulk-decaffeinate.
// Fix any style issues and re-enable lint.
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
const SandboxedModule = require('sandboxed-module') const SandboxedModule = require('sandboxed-module')
const sinon = require('sinon') const sinon = require('sinon')
const modulePath = require('path').join( const modulePath = require('path').join(
@ -34,7 +24,7 @@ describe('MongoManager', function () {
this.project_id = ObjectId().toString() this.project_id = ObjectId().toString()
this.doc_id = ObjectId().toString() this.doc_id = ObjectId().toString()
this.callback = sinon.stub() this.callback = sinon.stub()
return (this.stubbedErr = new Error('hello world')) this.stubbedErr = new Error('hello world')
}) })
describe('findDoc', function () { describe('findDoc', function () {
@ -42,7 +32,7 @@ describe('MongoManager', function () {
this.doc = { name: 'mock-doc' } this.doc = { name: 'mock-doc' }
this.db.docs.findOne = sinon.stub().callsArgWith(2, null, this.doc) this.db.docs.findOne = sinon.stub().callsArgWith(2, null, this.doc)
this.filter = { lines: true } this.filter = { lines: true }
return this.MongoManager.findDoc( this.MongoManager.findDoc(
this.project_id, this.project_id,
this.doc_id, this.doc_id,
this.filter, this.filter,
@ -64,8 +54,8 @@ describe('MongoManager', function () {
.should.equal(true) .should.equal(true)
}) })
return it('should call the callback with the doc', function () { it('should call the callback with the doc', function () {
return this.callback.calledWith(null, this.doc).should.equal(true) this.callback.calledWith(null, this.doc).should.equal(true)
}) })
}) })
@ -112,7 +102,7 @@ describe('MongoManager', function () {
describe('with included_deleted = false', function () { describe('with included_deleted = false', function () {
beforeEach(function () { beforeEach(function () {
return this.MongoManager.getProjectsDocs( this.MongoManager.getProjectsDocs(
this.project_id, this.project_id,
{ include_deleted: false }, { include_deleted: false },
this.filter, this.filter,
@ -121,7 +111,7 @@ describe('MongoManager', function () {
}) })
it('should find the non-deleted docs via the project_id', function () { it('should find the non-deleted docs via the project_id', function () {
return this.db.docs.find this.db.docs.find
.calledWith( .calledWith(
{ {
project_id: ObjectId(this.project_id), project_id: ObjectId(this.project_id),
@ -134,16 +124,16 @@ describe('MongoManager', function () {
.should.equal(true) .should.equal(true)
}) })
return it('should call the callback with the docs', function () { it('should call the callback with the docs', function () {
return this.callback this.callback
.calledWith(null, [this.doc, this.doc3, this.doc4]) .calledWith(null, [this.doc, this.doc3, this.doc4])
.should.equal(true) .should.equal(true)
}) })
}) })
return describe('with included_deleted = true', function () { describe('with included_deleted = true', function () {
beforeEach(function () { beforeEach(function () {
return this.MongoManager.getProjectsDocs( this.MongoManager.getProjectsDocs(
this.project_id, this.project_id,
{ include_deleted: true }, { include_deleted: true },
this.filter, this.filter,
@ -152,7 +142,7 @@ describe('MongoManager', function () {
}) })
it('should find all via the project_id', function () { it('should find all via the project_id', function () {
return this.db.docs.find this.db.docs.find
.calledWith( .calledWith(
{ {
project_id: ObjectId(this.project_id), project_id: ObjectId(this.project_id),
@ -164,8 +154,8 @@ describe('MongoManager', function () {
.should.equal(true) .should.equal(true)
}) })
return it('should call the callback with the docs', function () { it('should call the callback with the docs', function () {
return this.callback this.callback
.calledWith(null, [this.doc, this.doc3, this.doc4]) .calledWith(null, [this.doc, this.doc3, this.doc4])
.should.equal(true) .should.equal(true)
}) })
@ -218,11 +208,11 @@ describe('MongoManager', function () {
describe('upsertIntoDocCollection', function () { describe('upsertIntoDocCollection', function () {
beforeEach(function () { beforeEach(function () {
this.db.docs.updateOne = sinon.stub().callsArgWith(3, this.stubbedErr) this.db.docs.updateOne = sinon.stub().callsArgWith(3, this.stubbedErr)
return (this.oldRev = 77) this.oldRev = 77
}) })
it('should upsert the document', function (done) { it('should upsert the document', function (done) {
return this.MongoManager.upsertIntoDocCollection( this.MongoManager.upsertIntoDocCollection(
this.project_id, this.project_id,
this.doc_id, this.doc_id,
{ lines: this.lines }, { lines: this.lines },
@ -233,19 +223,19 @@ describe('MongoManager', function () {
assert.equal(args[1].$set.lines, this.lines) assert.equal(args[1].$set.lines, this.lines)
assert.equal(args[1].$inc.rev, 1) assert.equal(args[1].$inc.rev, 1)
assert.deepEqual(args[1].$set.project_id, ObjectId(this.project_id)) assert.deepEqual(args[1].$set.project_id, ObjectId(this.project_id))
return done() done()
} }
) )
}) })
return it('should return the error', function (done) { it('should return the error', function (done) {
return this.MongoManager.upsertIntoDocCollection( this.MongoManager.upsertIntoDocCollection(
this.project_id, this.project_id,
this.doc_id, this.doc_id,
{ lines: this.lines }, { lines: this.lines },
err => { err => {
err.should.equal(this.stubbedErr) err.should.equal(this.stubbedErr)
return done() done()
} }
) )
}) })
@ -255,17 +245,17 @@ describe('MongoManager', function () {
beforeEach(function (done) { beforeEach(function (done) {
this.db.docs.deleteOne = sinon.stub().yields() this.db.docs.deleteOne = sinon.stub().yields()
this.db.docOps.deleteOne = sinon.stub().yields() this.db.docOps.deleteOne = sinon.stub().yields()
return this.MongoManager.destroyDoc('123456789012', done) this.MongoManager.destroyDoc('123456789012', done)
}) })
it('should destroy the doc', function () { it('should destroy the doc', function () {
return sinon.assert.calledWith(this.db.docs.deleteOne, { sinon.assert.calledWith(this.db.docs.deleteOne, {
_id: ObjectId('123456789012'), _id: ObjectId('123456789012'),
}) })
}) })
return it('should destroy the docOps', function () { it('should destroy the docOps', function () {
return sinon.assert.calledWith(this.db.docOps.deleteOne, { sinon.assert.calledWith(this.db.docOps.deleteOne, {
doc_id: ObjectId('123456789012'), doc_id: ObjectId('123456789012'),
}) })
}) })
@ -276,11 +266,11 @@ describe('MongoManager', function () {
beforeEach(function () { beforeEach(function () {
this.doc = { version: (this.version = 42) } this.doc = { version: (this.version = 42) }
this.db.docOps.findOne = sinon.stub().callsArgWith(2, null, this.doc) this.db.docOps.findOne = sinon.stub().callsArgWith(2, null, this.doc)
return this.MongoManager.getDocVersion(this.doc_id, this.callback) this.MongoManager.getDocVersion(this.doc_id, this.callback)
}) })
it('should look for the doc in the database', function () { it('should look for the doc in the database', function () {
return this.db.docOps.findOne this.db.docOps.findOne
.calledWith( .calledWith(
{ doc_id: ObjectId(this.doc_id) }, { doc_id: ObjectId(this.doc_id) },
{ {
@ -290,19 +280,19 @@ describe('MongoManager', function () {
.should.equal(true) .should.equal(true)
}) })
return it('should call the callback with the version', function () { it('should call the callback with the version', function () {
return this.callback.calledWith(null, this.version).should.equal(true) this.callback.calledWith(null, this.version).should.equal(true)
}) })
}) })
return describe("when the doc doesn't exist", function () { describe("when the doc doesn't exist", function () {
beforeEach(function () { beforeEach(function () {
this.db.docOps.findOne = sinon.stub().callsArgWith(2, null, null) this.db.docOps.findOne = sinon.stub().callsArgWith(2, null, null)
return this.MongoManager.getDocVersion(this.doc_id, this.callback) this.MongoManager.getDocVersion(this.doc_id, this.callback)
}) })
return it('should call the callback with 0', function () { it('should call the callback with 0', function () {
return this.callback.calledWith(null, 0).should.equal(true) this.callback.calledWith(null, 0).should.equal(true)
}) })
}) })
}) })
@ -311,15 +301,11 @@ describe('MongoManager', function () {
beforeEach(function () { beforeEach(function () {
this.version = 42 this.version = 42
this.db.docOps.updateOne = sinon.stub().callsArg(3) this.db.docOps.updateOne = sinon.stub().callsArg(3)
return this.MongoManager.setDocVersion( this.MongoManager.setDocVersion(this.doc_id, this.version, this.callback)
this.doc_id,
this.version,
this.callback
)
}) })
it('should update the doc version', function () { it('should update the doc version', function () {
return this.db.docOps.updateOne this.db.docOps.updateOne
.calledWith( .calledWith(
{ {
doc_id: ObjectId(this.doc_id), doc_id: ObjectId(this.doc_id),
@ -336,8 +322,8 @@ describe('MongoManager', function () {
.should.equal(true) .should.equal(true)
}) })
return it('should call the callback', function () { it('should call the callback', function () {
return this.callback.called.should.equal(true) this.callback.called.should.equal(true)
}) })
}) })