mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-07 20:31:06 -05:00
convert TpdsUpdateSender to async and cleanup
GitOrigin-RevId: a19830134a13a23775c604a05a7e093d00bbb2de
This commit is contained in:
parent
419100d167
commit
9c87ad9801
4 changed files with 349 additions and 463 deletions
|
@ -1194,13 +1194,18 @@ const ProjectEntityUpdateHandler = {
|
||||||
project.overleaf &&
|
project.overleaf &&
|
||||||
project.overleaf.history &&
|
project.overleaf.history &&
|
||||||
project.overleaf.history.id
|
project.overleaf.history.id
|
||||||
TpdsUpdateSender.moveEntity({
|
// do not wait
|
||||||
project_id: projectId,
|
TpdsUpdateSender.promises
|
||||||
project_name: project.name,
|
.moveEntity({
|
||||||
startPath,
|
project_id: projectId,
|
||||||
endPath,
|
project_name: project.name,
|
||||||
rev
|
startPath,
|
||||||
})
|
endPath,
|
||||||
|
rev
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
logger.error({ err }, 'error sending tpds update')
|
||||||
|
})
|
||||||
DocumentUpdaterHandler.updateProjectStructure(
|
DocumentUpdaterHandler.updateProjectStructure(
|
||||||
projectId,
|
projectId,
|
||||||
projectHistoryId,
|
projectHistoryId,
|
||||||
|
@ -1243,13 +1248,18 @@ const ProjectEntityUpdateHandler = {
|
||||||
project.overleaf &&
|
project.overleaf &&
|
||||||
project.overleaf.history &&
|
project.overleaf.history &&
|
||||||
project.overleaf.history.id
|
project.overleaf.history.id
|
||||||
TpdsUpdateSender.moveEntity({
|
// do not wait
|
||||||
project_id: projectId,
|
TpdsUpdateSender.promises
|
||||||
project_name: project.name,
|
.moveEntity({
|
||||||
startPath,
|
project_id: projectId,
|
||||||
endPath,
|
project_name: project.name,
|
||||||
rev
|
startPath,
|
||||||
})
|
endPath,
|
||||||
|
rev
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
logger.error({ err }, 'error sending tpds update')
|
||||||
|
})
|
||||||
DocumentUpdaterHandler.updateProjectStructure(
|
DocumentUpdaterHandler.updateProjectStructure(
|
||||||
projectId,
|
projectId,
|
||||||
projectHistoryId,
|
projectHistoryId,
|
||||||
|
|
|
@ -1,306 +1,187 @@
|
||||||
/* eslint-disable
|
const _ = require('lodash')
|
||||||
camelcase,
|
const { callbackify } = require('util')
|
||||||
handle-callback-err,
|
|
||||||
max-len,
|
|
||||||
no-irregular-whitespace,
|
|
||||||
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
|
|
||||||
* DS207: Consider shorter variations of null checks
|
|
||||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
|
||||||
*/
|
|
||||||
let tpdsUrl
|
|
||||||
const settings = require('settings-sharelatex')
|
|
||||||
const logger = require('logger-sharelatex')
|
const logger = require('logger-sharelatex')
|
||||||
const path = require('path')
|
|
||||||
const ProjectGetter = require('../Project/ProjectGetter')
|
|
||||||
const keys = require('../../infrastructure/Keys')
|
|
||||||
const metrics = require('metrics-sharelatex')
|
const metrics = require('metrics-sharelatex')
|
||||||
const request = require('request')
|
const path = require('path')
|
||||||
|
const request = require('request-promise-native')
|
||||||
|
const settings = require('settings-sharelatex')
|
||||||
|
|
||||||
const CollaboratorsGetter = require('../Collaborators/CollaboratorsGetter')
|
const CollaboratorsGetter = require('../Collaborators/CollaboratorsGetter')
|
||||||
const { promisifyAll } = require('../../util/promises')
|
.promises
|
||||||
|
|
||||||
const buildPath = function(user_id, project_name, filePath) {
|
const tpdsUrl = _.get(settings, ['apis', 'thirdPartyDataStore', 'url'])
|
||||||
let projectPath = path.join(project_name, '/', filePath)
|
|
||||||
projectPath = encodeURIComponent(projectPath)
|
async function addDoc(options) {
|
||||||
const fullPath = path.join('/user/', `${user_id}`, '/entity/', projectPath)
|
metrics.inc('tpds.add-doc')
|
||||||
return fullPath
|
|
||||||
|
options.streamOrigin =
|
||||||
|
settings.apis.docstore.pubUrl +
|
||||||
|
path.join(
|
||||||
|
`/project/${options.project_id}`,
|
||||||
|
`/doc/${options.doc_id}`,
|
||||||
|
'/raw'
|
||||||
|
)
|
||||||
|
|
||||||
|
return addEntity(options)
|
||||||
}
|
}
|
||||||
|
|
||||||
const tpdsworkerEnabled = () =>
|
async function addEntity(options) {
|
||||||
(settings.apis.tpdsworker != null
|
const projectUserIds = await getProjectUsersIds(options.project_id)
|
||||||
? settings.apis.tpdsworker.url
|
if (!projectUserIds.length) {
|
||||||
: undefined) != null
|
return
|
||||||
if (!tpdsworkerEnabled()) {
|
}
|
||||||
logger.log('tpdsworker is not enabled, request will not be sent to it')
|
|
||||||
|
const job = {
|
||||||
|
method: 'post',
|
||||||
|
headers: {
|
||||||
|
sl_entity_rev: options.rev,
|
||||||
|
sl_project_id: options.project_id,
|
||||||
|
sl_all_user_ids: JSON.stringify(projectUserIds)
|
||||||
|
},
|
||||||
|
uri: buildTpdsUrl(projectUserIds[0], options.project_name, options.path),
|
||||||
|
title: 'addFile',
|
||||||
|
streamOrigin: options.streamOrigin
|
||||||
|
}
|
||||||
|
|
||||||
|
return enqueue(options.project_id, 'pipeStreamFrom', job)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.apis.thirdPartyDataStore.linode_url != null) {
|
async function addFile(options) {
|
||||||
tpdsUrl = settings.apis.thirdPartyDataStore.linode_url
|
metrics.inc('tpds.add-file')
|
||||||
} else {
|
|
||||||
tpdsUrl = settings.apis.thirdPartyDataStore.url
|
options.streamOrigin =
|
||||||
|
settings.apis.filestore.url +
|
||||||
|
path.join(`/project/${options.project_id}`, `/file/${options.file_id}`)
|
||||||
|
|
||||||
|
return addEntity(options)
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildMovePaths(options) {
|
||||||
|
if (options.newProjectName) {
|
||||||
|
return {
|
||||||
|
startPath: path.join('/', options.project_name, '/'),
|
||||||
|
endPath: path.join('/', options.newProjectName, '/')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
startPath: path.join('/', options.project_name, '/', options.startPath),
|
||||||
|
endPath: path.join('/', options.project_name, '/', options.endPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildTpdsUrl(userId, projectName, filePath) {
|
||||||
|
const projectPath = encodeURIComponent(path.join(projectName, '/', filePath))
|
||||||
|
return `${tpdsUrl}/user/${userId}/entity/${projectPath}`
|
||||||
|
}
|
||||||
|
|
||||||
|
async function deleteEntity(options) {
|
||||||
|
metrics.inc('tpds.delete-entity')
|
||||||
|
|
||||||
|
const projectUserIds = await getProjectUsersIds(options.project_id)
|
||||||
|
if (!projectUserIds.length) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const job = {
|
||||||
|
method: 'delete',
|
||||||
|
headers: {
|
||||||
|
sl_project_id: options.project_id,
|
||||||
|
sl_all_user_ids: JSON.stringify(projectUserIds)
|
||||||
|
},
|
||||||
|
uri: buildTpdsUrl(projectUserIds[0], options.project_name, options.path),
|
||||||
|
title: 'deleteEntity',
|
||||||
|
sl_all_user_ids: JSON.stringify(projectUserIds)
|
||||||
|
}
|
||||||
|
|
||||||
|
return enqueue(options.project_id, 'standardHttpRequest', job)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function enqueue(group, method, job) {
|
||||||
|
const tpdsWorkerUrl = _.get(settings, ['apis', 'tpdsworker', 'url'])
|
||||||
|
// silently do nothing if worker url is not in settings
|
||||||
|
if (!tpdsWorkerUrl) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return request({
|
||||||
|
uri: `${tpdsWorkerUrl}/enqueue/web_to_tpds_http_requests`,
|
||||||
|
json: { group, job, method },
|
||||||
|
method: 'post',
|
||||||
|
timeout: 5 * 1000
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
// log error and continue
|
||||||
|
logger.error({ err, group, job, method }, 'error enqueueing tpdsworker job')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getProjectUsersIds(projectId) {
|
||||||
|
// get list of all user ids with access to project. project owner
|
||||||
|
// will always be the first entry in the list.
|
||||||
|
// TODO: filter this list to only return users with dropbox linked
|
||||||
|
return CollaboratorsGetter.getInvitedMemberIds(projectId)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function moveEntity(options) {
|
||||||
|
metrics.inc('tpds.move-entity')
|
||||||
|
|
||||||
|
const projectUserIds = await getProjectUsersIds(options.project_id)
|
||||||
|
if (!projectUserIds.length) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const { endPath, startPath } = buildMovePaths(options)
|
||||||
|
|
||||||
|
const job = {
|
||||||
|
method: 'put',
|
||||||
|
title: 'moveEntity',
|
||||||
|
uri: `${tpdsUrl}/user/${projectUserIds[0]}/entity`,
|
||||||
|
headers: {
|
||||||
|
sl_project_id: options.project_id,
|
||||||
|
sl_entity_rev: options.rev,
|
||||||
|
sl_all_user_ids: JSON.stringify(projectUserIds)
|
||||||
|
},
|
||||||
|
json: {
|
||||||
|
user_id: projectUserIds[0],
|
||||||
|
endPath,
|
||||||
|
startPath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return enqueue(options.project_id, 'standardHttpRequest', job)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function pollDropboxForUser(userId) {
|
||||||
|
metrics.inc('tpds.poll-dropbox')
|
||||||
|
|
||||||
|
const job = {
|
||||||
|
method: 'post',
|
||||||
|
uri: `${tpdsUrl}/user/poll`,
|
||||||
|
json: {
|
||||||
|
user_ids: [userId]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return enqueue(`poll-dropbox:${userId}`, 'standardHttpRequest', job)
|
||||||
}
|
}
|
||||||
|
|
||||||
const TpdsUpdateSender = {
|
const TpdsUpdateSender = {
|
||||||
_enqueue(group, method, job, callback) {
|
addDoc: callbackify(addDoc),
|
||||||
if (!tpdsworkerEnabled()) {
|
addEntity: callbackify(addEntity),
|
||||||
return callback()
|
addFile: callbackify(addFile),
|
||||||
}
|
deleteEntity: callbackify(deleteEntity),
|
||||||
const opts = {
|
enqueue: callbackify(enqueue),
|
||||||
uri: `${settings.apis.tpdsworker.url}/enqueue/web_to_tpds_http_requests`,
|
moveEntity: callbackify(moveEntity),
|
||||||
json: {
|
pollDropboxForUser: callbackify(pollDropboxForUser),
|
||||||
group,
|
promises: {
|
||||||
method,
|
addDoc,
|
||||||
job
|
addEntity,
|
||||||
},
|
addFile,
|
||||||
method: 'post',
|
deleteEntity,
|
||||||
timeout: 5 * 1000
|
enqueue,
|
||||||
}
|
moveEntity,
|
||||||
return request(opts, function(err) {
|
pollDropboxForUser
|
||||||
if (err != null) {
|
|
||||||
logger.err(
|
|
||||||
{ err },
|
|
||||||
'error queuing something in the tpdsworker, continuing anyway'
|
|
||||||
)
|
|
||||||
return callback()
|
|
||||||
} else {
|
|
||||||
return callback()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
_addEntity(options, callback) {
|
|
||||||
if (callback == null) {
|
|
||||||
callback = function(err) {}
|
|
||||||
}
|
|
||||||
return getProjectsUsersIds(options.project_id, function(
|
|
||||||
err,
|
|
||||||
user_id,
|
|
||||||
allUserIds
|
|
||||||
) {
|
|
||||||
if (err != null) {
|
|
||||||
logger.warn({ err, options }, 'error getting projects user ids')
|
|
||||||
return callback(err)
|
|
||||||
}
|
|
||||||
logger.log(
|
|
||||||
{
|
|
||||||
project_id: options.project_id,
|
|
||||||
user_id,
|
|
||||||
path: options.path,
|
|
||||||
uri: options.uri,
|
|
||||||
rev: options.rev
|
|
||||||
},
|
|
||||||
'sending file to third party data store'
|
|
||||||
)
|
|
||||||
const postOptions = {
|
|
||||||
method: 'post',
|
|
||||||
headers: {
|
|
||||||
sl_entity_rev: options.rev,
|
|
||||||
sl_project_id: options.project_id,
|
|
||||||
sl_all_user_ids: JSON.stringify(allUserIds)
|
|
||||||
},
|
|
||||||
uri: `${tpdsUrl}${buildPath(
|
|
||||||
user_id,
|
|
||||||
options.project_name,
|
|
||||||
options.path
|
|
||||||
)}`,
|
|
||||||
title: 'addFile',
|
|
||||||
streamOrigin: options.streamOrigin
|
|
||||||
}
|
|
||||||
return TpdsUpdateSender._enqueue(
|
|
||||||
options.project_id,
|
|
||||||
'pipeStreamFrom',
|
|
||||||
postOptions,
|
|
||||||
function(err) {
|
|
||||||
if (err != null) {
|
|
||||||
logger.warn(
|
|
||||||
{
|
|
||||||
err,
|
|
||||||
project_id: options.project_id,
|
|
||||||
user_id,
|
|
||||||
path: options.path,
|
|
||||||
uri: options.uri,
|
|
||||||
rev: options.rev
|
|
||||||
},
|
|
||||||
'error sending file to third party data store queued up for processing'
|
|
||||||
)
|
|
||||||
return callback(err)
|
|
||||||
}
|
|
||||||
logger.log(
|
|
||||||
{
|
|
||||||
project_id: options.project_id,
|
|
||||||
user_id,
|
|
||||||
path: options.path,
|
|
||||||
uri: options.uri,
|
|
||||||
rev: options.rev
|
|
||||||
},
|
|
||||||
'sending file to third party data store queued up for processing'
|
|
||||||
)
|
|
||||||
return callback(err)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
addFile(options, callback) {
|
|
||||||
if (callback == null) {
|
|
||||||
callback = function(err) {}
|
|
||||||
}
|
|
||||||
metrics.inc('tpds.add-file')
|
|
||||||
options.streamOrigin =
|
|
||||||
(settings.apis.filestore.linode_url || settings.apis.filestore.url) +
|
|
||||||
path.join(`/project/${options.project_id}/file/`, `${options.file_id}`)
|
|
||||||
return this._addEntity(options, callback)
|
|
||||||
},
|
|
||||||
|
|
||||||
addDoc(options, callback) {
|
|
||||||
if (callback == null) {
|
|
||||||
callback = function(err) {}
|
|
||||||
}
|
|
||||||
metrics.inc('tpds.add-doc')
|
|
||||||
options.streamOrigin =
|
|
||||||
(settings.apis.docstore.linode_url || settings.apis.docstore.pubUrl) +
|
|
||||||
path.join(`/project/${options.project_id}/doc/`, `${options.doc_id}/raw`)
|
|
||||||
return this._addEntity(options, callback)
|
|
||||||
},
|
|
||||||
moveEntity(options, callback) {
|
|
||||||
let endPath, startPath
|
|
||||||
if (callback == null) {
|
|
||||||
callback = function(err) {}
|
|
||||||
}
|
|
||||||
metrics.inc('tpds.move-entity')
|
|
||||||
if (options.newProjectName != null) {
|
|
||||||
startPath = path.join(`/${options.project_name}/`)
|
|
||||||
endPath = path.join(`/${options.newProjectName}/`)
|
|
||||||
} else {
|
|
||||||
startPath = mergeProjectNameAndPath(
|
|
||||||
options.project_name,
|
|
||||||
options.startPath
|
|
||||||
)
|
|
||||||
endPath = mergeProjectNameAndPath(options.project_name, options.endPath)
|
|
||||||
}
|
|
||||||
return getProjectsUsersIds(options.project_id, function(
|
|
||||||
err,
|
|
||||||
user_id,
|
|
||||||
allUserIds
|
|
||||||
) {
|
|
||||||
const moveOptions = {
|
|
||||||
method: 'put',
|
|
||||||
title: 'moveEntity',
|
|
||||||
uri: `${tpdsUrl}/user/${user_id}/entity`,
|
|
||||||
headers: {
|
|
||||||
sl_project_id: options.project_id,
|
|
||||||
sl_entity_rev: options.rev,
|
|
||||||
sl_all_user_ids: JSON.stringify(allUserIds)
|
|
||||||
},
|
|
||||||
json: {
|
|
||||||
user_id,
|
|
||||||
endPath,
|
|
||||||
startPath
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TpdsUpdateSender._enqueue(
|
|
||||||
options.project_id,
|
|
||||||
'standardHttpRequest',
|
|
||||||
moveOptions,
|
|
||||||
callback
|
|
||||||
)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
deleteEntity(options, callback) {
|
|
||||||
if (callback == null) {
|
|
||||||
callback = function(err) {}
|
|
||||||
}
|
|
||||||
metrics.inc('tpds.delete-entity')
|
|
||||||
return getProjectsUsersIds(options.project_id, function(
|
|
||||||
err,
|
|
||||||
user_id,
|
|
||||||
allUserIds
|
|
||||||
) {
|
|
||||||
const deleteOptions = {
|
|
||||||
method: 'DELETE',
|
|
||||||
headers: {
|
|
||||||
sl_project_id: options.project_id,
|
|
||||||
sl_all_user_ids: JSON.stringify(allUserIds)
|
|
||||||
},
|
|
||||||
uri: `${tpdsUrl}${buildPath(
|
|
||||||
user_id,
|
|
||||||
options.project_name,
|
|
||||||
options.path
|
|
||||||
)}`,
|
|
||||||
title: 'deleteEntity',
|
|
||||||
sl_all_user_ids: JSON.stringify(allUserIds)
|
|
||||||
}
|
|
||||||
return TpdsUpdateSender._enqueue(
|
|
||||||
options.project_id,
|
|
||||||
'standardHttpRequest',
|
|
||||||
deleteOptions,
|
|
||||||
callback
|
|
||||||
)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
pollDropboxForUser(user_id, callback) {
|
|
||||||
if (callback == null) {
|
|
||||||
callback = function(err) {}
|
|
||||||
}
|
|
||||||
metrics.inc('tpds.poll-dropbox')
|
|
||||||
const options = {
|
|
||||||
method: 'POST',
|
|
||||||
uri: `${tpdsUrl}/user/poll`,
|
|
||||||
json: {
|
|
||||||
user_ids: [user_id]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TpdsUpdateSender._enqueue(
|
|
||||||
`poll-dropbox:${user_id}`,
|
|
||||||
'standardHttpRequest',
|
|
||||||
options,
|
|
||||||
callback
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var getProjectsUsersIds = function(project_id, callback) {
|
|
||||||
if (callback == null) {
|
|
||||||
callback = function(err, owner_id, allUserIds) {}
|
|
||||||
}
|
|
||||||
return ProjectGetter.getProject(
|
|
||||||
project_id,
|
|
||||||
{ _id: true, owner_ref: true },
|
|
||||||
function(err, project) {
|
|
||||||
if (err != null) {
|
|
||||||
return callback(err)
|
|
||||||
}
|
|
||||||
return CollaboratorsGetter.getInvitedMemberIds(project_id, function(
|
|
||||||
err,
|
|
||||||
member_ids
|
|
||||||
) {
|
|
||||||
if (err != null) {
|
|
||||||
return callback(err)
|
|
||||||
}
|
|
||||||
return callback(
|
|
||||||
err,
|
|
||||||
project != null ? project.owner_ref : undefined,
|
|
||||||
member_ids
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
var mergeProjectNameAndPath = function(project_name, path) {
|
|
||||||
if (path.indexOf('/') === 0) {
|
|
||||||
path = path.substring(1)
|
|
||||||
}
|
|
||||||
const fullPath = `/${project_name}/${path}`
|
|
||||||
return fullPath
|
|
||||||
}
|
|
||||||
|
|
||||||
TpdsUpdateSender.promises = promisifyAll(TpdsUpdateSender)
|
|
||||||
module.exports = TpdsUpdateSender
|
module.exports = TpdsUpdateSender
|
||||||
|
|
|
@ -133,7 +133,10 @@ describe('ProjectEntityUpdateHandler', function() {
|
||||||
addFile: sinon.stub().yields(),
|
addFile: sinon.stub().yields(),
|
||||||
addDoc: sinon.stub(),
|
addDoc: sinon.stub(),
|
||||||
deleteEntity: sinon.stub().yields(),
|
deleteEntity: sinon.stub().yields(),
|
||||||
moveEntity: sinon.stub()
|
moveEntity: sinon.stub(),
|
||||||
|
promises: {
|
||||||
|
moveEntity: sinon.stub().resolves()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.FileStoreHandler = {
|
this.FileStoreHandler = {
|
||||||
copyFile: sinon.stub(),
|
copyFile: sinon.stub(),
|
||||||
|
@ -1672,7 +1675,7 @@ describe('ProjectEntityUpdateHandler', function() {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('notifies tpds', function() {
|
it('notifies tpds', function() {
|
||||||
this.TpdsUpdateSender.moveEntity
|
this.TpdsUpdateSender.promises.moveEntity
|
||||||
.calledWith({
|
.calledWith({
|
||||||
project_id: projectId,
|
project_id: projectId,
|
||||||
project_name: this.project_name,
|
project_name: this.project_name,
|
||||||
|
@ -1731,7 +1734,7 @@ describe('ProjectEntityUpdateHandler', function() {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('notifies tpds', function() {
|
it('notifies tpds', function() {
|
||||||
this.TpdsUpdateSender.moveEntity
|
this.TpdsUpdateSender.promises.moveEntity
|
||||||
.calledWith({
|
.calledWith({
|
||||||
project_id: projectId,
|
project_id: projectId,
|
||||||
project_name: this.project_name,
|
project_name: this.project_name,
|
||||||
|
|
|
@ -1,31 +1,20 @@
|
||||||
/* eslint-disable
|
|
||||||
camelcase,
|
|
||||||
handle-callback-err,
|
|
||||||
max-len,
|
|
||||||
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 assert = require('assert')
|
const chai = require('chai')
|
||||||
require('chai').should()
|
const path = require('path')
|
||||||
const modulePath = require('path').join(
|
const sinon = require('sinon')
|
||||||
|
|
||||||
|
chai.should()
|
||||||
|
|
||||||
|
const modulePath = path.join(
|
||||||
__dirname,
|
__dirname,
|
||||||
'../../../../app/src/Features/ThirdPartyDataStore/TpdsUpdateSender.js'
|
'../../../../app/src/Features/ThirdPartyDataStore/TpdsUpdateSender.js'
|
||||||
)
|
)
|
||||||
const sinon = require('sinon')
|
|
||||||
const ath = require('path')
|
const projectId = 'project_id_here'
|
||||||
const project_id = 'project_id_here'
|
const userId = 'user_id_here'
|
||||||
const user_id = 'user_id_here'
|
const readOnlyRef = 'read_only_ref_1_id_here'
|
||||||
const read_only_ref_1 = 'read_only_ref_1_id_here'
|
const collaberatorRef = 'collaberator_ref_1_here'
|
||||||
const collaberator_ref_1 = 'collaberator_ref_1_here'
|
const projectName = 'project_name_here'
|
||||||
const project_name = 'project_name_here'
|
|
||||||
|
|
||||||
const thirdPartyDataStoreApiUrl = 'http://third-party-json-store.herokuapp.com'
|
const thirdPartyDataStoreApiUrl = 'http://third-party-json-store.herokuapp.com'
|
||||||
const httpUsername = 'user'
|
const httpUsername = 'user'
|
||||||
|
@ -37,16 +26,14 @@ const filestoreUrl = 'filestore.sharelatex.com'
|
||||||
describe('TpdsUpdateSender', function() {
|
describe('TpdsUpdateSender', function() {
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
this.requestQueuer = function(queue, meth, opts, callback) {}
|
this.requestQueuer = function(queue, meth, opts, callback) {}
|
||||||
const project = { owner_ref: user_id }
|
const memberIds = [userId, collaberatorRef, readOnlyRef]
|
||||||
const member_ids = [collaberator_ref_1, read_only_ref_1, user_id]
|
|
||||||
this.CollaboratorsGetter = {
|
this.CollaboratorsGetter = {
|
||||||
getInvitedMemberIds: sinon.stub().yields(null, member_ids)
|
promises: {
|
||||||
}
|
getInvitedMemberIds: sinon.stub().resolves(memberIds)
|
||||||
this.ProjectGetter = {
|
}
|
||||||
getProject: sinon.stub().callsArgWith(2, null, project)
|
|
||||||
}
|
}
|
||||||
this.docstoreUrl = 'docstore.sharelatex.env'
|
this.docstoreUrl = 'docstore.sharelatex.env'
|
||||||
this.request = sinon.stub().returns({ pipe() {} })
|
this.request = sinon.stub().resolves()
|
||||||
this.settings = {
|
this.settings = {
|
||||||
siteUrl,
|
siteUrl,
|
||||||
httpAuthSiteUrl,
|
httpAuthSiteUrl,
|
||||||
|
@ -60,182 +47,187 @@ describe('TpdsUpdateSender', function() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (this.updateSender = SandboxedModule.require(modulePath, {
|
this.updateSender = SandboxedModule.require(modulePath, {
|
||||||
globals: {
|
globals: {
|
||||||
console: console
|
console: console
|
||||||
},
|
},
|
||||||
requires: {
|
requires: {
|
||||||
'settings-sharelatex': this.settings,
|
'settings-sharelatex': this.settings,
|
||||||
'logger-sharelatex': { log() {} },
|
'logger-sharelatex': { log() {} },
|
||||||
'../Project/ProjectGetter': this.ProjectGetter,
|
'request-promise-native': this.request,
|
||||||
request: this.request,
|
|
||||||
'../Collaborators/CollaboratorsGetter': this.CollaboratorsGetter,
|
'../Collaborators/CollaboratorsGetter': this.CollaboratorsGetter,
|
||||||
'metrics-sharelatex': {
|
'metrics-sharelatex': {
|
||||||
inc() {}
|
inc() {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}))
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('_enqueue', function() {
|
describe('enqueue', function() {
|
||||||
it('should not call request if there is no tpdsworker url', function(done) {
|
it('should not call request if there is no tpdsworker url', async function() {
|
||||||
return this.updateSender._enqueue(null, null, null, err => {
|
await this.updateSender.promises.enqueue(null, null, null)
|
||||||
this.request.called.should.equal(false)
|
this.request.should.not.have.been.called
|
||||||
return done()
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should post the message to the tpdsworker', function(done) {
|
it('should post the message to the tpdsworker', async function() {
|
||||||
this.settings.apis.tpdsworker = { url: 'www.tpdsworker.env' }
|
this.settings.apis.tpdsworker = { url: 'www.tpdsworker.env' }
|
||||||
const group = 'myproject'
|
const group = 'myproject'
|
||||||
const method = 'somemethod'
|
const method = 'somemethod'
|
||||||
const job = 'do something'
|
const job = 'do something'
|
||||||
this.request.callsArgWith(1)
|
await this.updateSender.promises.enqueue(group, method, job)
|
||||||
return this.updateSender._enqueue(group, method, job, err => {
|
const args = this.request.firstCall.args[0]
|
||||||
const args = this.request.args[0][0]
|
args.json.group.should.equal(group)
|
||||||
args.json.group.should.equal(group)
|
args.json.job.should.equal(job)
|
||||||
args.json.job.should.equal(job)
|
args.json.method.should.equal(method)
|
||||||
args.json.method.should.equal(method)
|
args.uri.should.equal(
|
||||||
args.uri.should.equal(
|
'www.tpdsworker.env/enqueue/web_to_tpds_http_requests'
|
||||||
'www.tpdsworker.env/enqueue/web_to_tpds_http_requests'
|
)
|
||||||
)
|
|
||||||
return done()
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('sending updates', function() {
|
describe('sending updates', function() {
|
||||||
it('queues a post the file with user and file id', function(done) {
|
beforeEach(function() {
|
||||||
const file_id = '4545345'
|
this.settings.apis.tpdsworker = { url: 'www.tpdsworker.env' }
|
||||||
|
})
|
||||||
|
|
||||||
|
it('queues a post the file with user and file id', async function() {
|
||||||
|
const fileId = '4545345'
|
||||||
const path = '/some/path/here.jpg'
|
const path = '/some/path/here.jpg'
|
||||||
this.updateSender._enqueue = function(uid, method, job, callback) {
|
|
||||||
uid.should.equal(project_id)
|
await this.updateSender.promises.addFile({
|
||||||
job.method.should.equal('post')
|
project_id: projectId,
|
||||||
job.streamOrigin.should.equal(
|
file_id: fileId,
|
||||||
`${filestoreUrl}/project/${project_id}/file/${file_id}`
|
path,
|
||||||
)
|
project_name: projectName
|
||||||
const expectedUrl = `${thirdPartyDataStoreApiUrl}/user/${user_id}/entity/${encodeURIComponent(
|
})
|
||||||
project_name
|
|
||||||
)}${encodeURIComponent(path)}`
|
const { group, job, method } = this.request.firstCall.args[0].json
|
||||||
job.uri.should.equal(expectedUrl)
|
group.should.equal(projectId)
|
||||||
job.headers.sl_all_user_ids.should.eql(
|
method.should.equal('pipeStreamFrom')
|
||||||
JSON.stringify([collaberator_ref_1, read_only_ref_1, user_id])
|
job.method.should.equal('post')
|
||||||
)
|
job.streamOrigin.should.equal(
|
||||||
return done()
|
`${filestoreUrl}/project/${projectId}/file/${fileId}`
|
||||||
}
|
)
|
||||||
return this.updateSender.addFile(
|
const expectedUrl = `${thirdPartyDataStoreApiUrl}/user/${userId}/entity/${encodeURIComponent(
|
||||||
{ project_id, file_id, path, project_name },
|
projectName
|
||||||
() => {}
|
)}${encodeURIComponent(path)}`
|
||||||
|
job.uri.should.equal(expectedUrl)
|
||||||
|
job.headers.sl_all_user_ids.should.equal(
|
||||||
|
JSON.stringify([userId, collaberatorRef, readOnlyRef])
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('post doc with stream origin of docstore', function(done) {
|
it('post doc with stream origin of docstore', async function() {
|
||||||
const doc_id = '4545345'
|
const docId = '4545345'
|
||||||
const path = '/some/path/here.tex'
|
const path = '/some/path/here.tex'
|
||||||
const lines = ['line1', 'line2', 'line3']
|
const lines = ['line1', 'line2', 'line3']
|
||||||
|
|
||||||
this.updateSender._enqueue = (uid, method, job, callback) => {
|
await this.updateSender.promises.addDoc({
|
||||||
uid.should.equal(project_id)
|
project_id: projectId,
|
||||||
job.method.should.equal('post')
|
doc_id: docId,
|
||||||
const expectedUrl = `${thirdPartyDataStoreApiUrl}/user/${user_id}/entity/${encodeURIComponent(
|
|
||||||
project_name
|
|
||||||
)}${encodeURIComponent(path)}`
|
|
||||||
job.uri.should.equal(expectedUrl)
|
|
||||||
job.streamOrigin.should.equal(
|
|
||||||
`${this.docstoreUrl}/project/${project_id}/doc/${doc_id}/raw`
|
|
||||||
)
|
|
||||||
job.headers.sl_all_user_ids.should.eql(
|
|
||||||
JSON.stringify([collaberator_ref_1, read_only_ref_1, user_id])
|
|
||||||
)
|
|
||||||
return done()
|
|
||||||
}
|
|
||||||
return this.updateSender.addDoc({
|
|
||||||
project_id,
|
|
||||||
doc_id,
|
|
||||||
path,
|
path,
|
||||||
docLines: lines,
|
docLines: lines,
|
||||||
project_name
|
project_name: projectName
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const { group, job, method } = this.request.firstCall.args[0].json
|
||||||
|
|
||||||
|
group.should.equal(projectId)
|
||||||
|
method.should.equal('pipeStreamFrom')
|
||||||
|
job.method.should.equal('post')
|
||||||
|
const expectedUrl = `${thirdPartyDataStoreApiUrl}/user/${userId}/entity/${encodeURIComponent(
|
||||||
|
projectName
|
||||||
|
)}${encodeURIComponent(path)}`
|
||||||
|
job.uri.should.equal(expectedUrl)
|
||||||
|
job.streamOrigin.should.equal(
|
||||||
|
`${this.docstoreUrl}/project/${projectId}/doc/${docId}/raw`
|
||||||
|
)
|
||||||
|
job.headers.sl_all_user_ids.should.eql(
|
||||||
|
JSON.stringify([userId, collaberatorRef, readOnlyRef])
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('deleting entity', function(done) {
|
it('deleting entity', async function() {
|
||||||
const path = '/path/here/t.tex'
|
const path = '/path/here/t.tex'
|
||||||
this.updateSender._enqueue = function(uid, method, job, callback) {
|
|
||||||
uid.should.equal(project_id)
|
await this.updateSender.promises.deleteEntity({
|
||||||
job.method.should.equal('DELETE')
|
project_id: projectId,
|
||||||
const expectedUrl = `${thirdPartyDataStoreApiUrl}/user/${user_id}/entity/${encodeURIComponent(
|
path,
|
||||||
project_name
|
project_name: projectName
|
||||||
)}${encodeURIComponent(path)}`
|
})
|
||||||
job.headers.sl_all_user_ids.should.eql(
|
|
||||||
JSON.stringify([collaberator_ref_1, read_only_ref_1, user_id])
|
const { group, job, method } = this.request.firstCall.args[0].json
|
||||||
)
|
|
||||||
job.uri.should.equal(expectedUrl)
|
group.should.equal(projectId)
|
||||||
return done()
|
method.should.equal('standardHttpRequest')
|
||||||
}
|
job.method.should.equal('delete')
|
||||||
return this.updateSender.deleteEntity({ project_id, path, project_name })
|
const expectedUrl = `${thirdPartyDataStoreApiUrl}/user/${userId}/entity/${encodeURIComponent(
|
||||||
|
projectName
|
||||||
|
)}${encodeURIComponent(path)}`
|
||||||
|
job.headers.sl_all_user_ids.should.eql(
|
||||||
|
JSON.stringify([userId, collaberatorRef, readOnlyRef])
|
||||||
|
)
|
||||||
|
job.uri.should.equal(expectedUrl)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('moving entity', function(done) {
|
it('moving entity', async function() {
|
||||||
const startPath = 'staring/here/file.tex'
|
const startPath = 'staring/here/file.tex'
|
||||||
const endPath = 'ending/here/file.tex'
|
const endPath = 'ending/here/file.tex'
|
||||||
this.updateSender._enqueue = function(uid, method, job, callback) {
|
|
||||||
uid.should.equal(project_id)
|
await this.updateSender.promises.moveEntity({
|
||||||
job.method.should.equal('put')
|
project_id: projectId,
|
||||||
job.uri.should.equal(
|
|
||||||
`${thirdPartyDataStoreApiUrl}/user/${user_id}/entity`
|
|
||||||
)
|
|
||||||
job.json.startPath.should.equal(`/${project_name}/${startPath}`)
|
|
||||||
job.json.endPath.should.equal(`/${project_name}/${endPath}`)
|
|
||||||
job.headers.sl_all_user_ids.should.eql(
|
|
||||||
JSON.stringify([collaberator_ref_1, read_only_ref_1, user_id])
|
|
||||||
)
|
|
||||||
return done()
|
|
||||||
}
|
|
||||||
return this.updateSender.moveEntity({
|
|
||||||
project_id,
|
|
||||||
startPath,
|
startPath,
|
||||||
endPath,
|
endPath,
|
||||||
project_name
|
project_name: projectName
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const { group, job, method } = this.request.firstCall.args[0].json
|
||||||
|
|
||||||
|
group.should.equal(projectId)
|
||||||
|
method.should.equal('standardHttpRequest')
|
||||||
|
job.method.should.equal('put')
|
||||||
|
job.uri.should.equal(`${thirdPartyDataStoreApiUrl}/user/${userId}/entity`)
|
||||||
|
job.json.startPath.should.equal(`/${projectName}/${startPath}`)
|
||||||
|
job.json.endPath.should.equal(`/${projectName}/${endPath}`)
|
||||||
|
job.headers.sl_all_user_ids.should.eql(
|
||||||
|
JSON.stringify([userId, collaberatorRef, readOnlyRef])
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should be able to rename a project using the move entity func', function(done) {
|
it('should be able to rename a project using the move entity func', async function() {
|
||||||
const oldProjectName = '/oldProjectName/'
|
const oldProjectName = '/oldProjectName/'
|
||||||
const newProjectName = '/newProjectName/'
|
const newProjectName = '/newProjectName/'
|
||||||
this.updateSender._enqueue = function(uid, method, job, callback) {
|
|
||||||
uid.should.equal(project_id)
|
await this.updateSender.promises.moveEntity({
|
||||||
job.method.should.equal('put')
|
project_id: projectId,
|
||||||
job.uri.should.equal(
|
|
||||||
`${thirdPartyDataStoreApiUrl}/user/${user_id}/entity`
|
|
||||||
)
|
|
||||||
job.json.startPath.should.equal(oldProjectName)
|
|
||||||
job.json.endPath.should.equal(newProjectName)
|
|
||||||
job.headers.sl_all_user_ids.should.eql(
|
|
||||||
JSON.stringify([collaberator_ref_1, read_only_ref_1, user_id])
|
|
||||||
)
|
|
||||||
return done()
|
|
||||||
}
|
|
||||||
return this.updateSender.moveEntity({
|
|
||||||
project_id,
|
|
||||||
project_name: oldProjectName,
|
project_name: oldProjectName,
|
||||||
newProjectName
|
newProjectName
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const { group, job, method } = this.request.firstCall.args[0].json
|
||||||
|
|
||||||
|
group.should.equal(projectId)
|
||||||
|
method.should.equal('standardHttpRequest')
|
||||||
|
job.method.should.equal('put')
|
||||||
|
job.uri.should.equal(`${thirdPartyDataStoreApiUrl}/user/${userId}/entity`)
|
||||||
|
job.json.startPath.should.equal(oldProjectName)
|
||||||
|
job.json.endPath.should.equal(newProjectName)
|
||||||
|
job.headers.sl_all_user_ids.should.eql(
|
||||||
|
JSON.stringify([userId, collaberatorRef, readOnlyRef])
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('pollDropboxForUser', function(done) {
|
it('pollDropboxForUser', async function() {
|
||||||
this.updateSender._enqueue = sinon.stub().callsArg(3)
|
await this.updateSender.promises.pollDropboxForUser(userId)
|
||||||
return this.updateSender.pollDropboxForUser(user_id, error => {
|
|
||||||
this.updateSender._enqueue
|
const { group, job, method } = this.request.firstCall.args[0].json
|
||||||
.calledWith(`poll-dropbox:${user_id}`, 'standardHttpRequest', {
|
|
||||||
method: 'POST',
|
group.should.equal(`poll-dropbox:${userId}`)
|
||||||
uri: `${thirdPartyDataStoreApiUrl}/user/poll`,
|
method.should.equal('standardHttpRequest')
|
||||||
json: {
|
|
||||||
user_ids: [user_id]
|
job.method.should.equal('post')
|
||||||
}
|
job.uri.should.equal(`${thirdPartyDataStoreApiUrl}/user/poll`)
|
||||||
})
|
job.json.user_ids[0].should.equal(userId)
|
||||||
.should.equal(true)
|
|
||||||
return done()
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in a new issue