Merge pull request #4003 from overleaf/bg-project-archiver-deletion

project archiver deletion of expired projects

GitOrigin-RevId: 7e010f4883e0bfeb593da6b728c8e4ac329824cd
This commit is contained in:
Brian Gough 2021-05-11 09:49:39 +01:00 committed by Copybot
parent 6965b27c05
commit 1d94ef5b54
4 changed files with 61 additions and 0 deletions

View file

@ -15,6 +15,7 @@ const DocstoreManager = require('../Docstore/DocstoreManager')
const EditorRealTimeController = require('../Editor/EditorRealTimeController')
const HistoryManager = require('../History/HistoryManager')
const FilestoreHandler = require('../FileStore/FileStoreHandler')
const TpdsUpdateSender = require('../ThirdPartyDataStore/TpdsUpdateSender')
const moment = require('moment')
const { promiseMapWithLimit } = require('../../util/promises')
@ -369,6 +370,9 @@ async function expireDeletedProject(projectId) {
historyId
),
FilestoreHandler.promises.deleteProject(deletedProject.project._id),
TpdsUpdateSender.promises.deleteProject({
project_id: deletedProject.project._id,
}),
hardDeleteDeletedFiles(deletedProject.project._id),
])

View file

@ -99,6 +99,33 @@ async function deleteEntity(options) {
}
}
async function deleteProject(options) {
// deletion only applies to project archiver
const projectArchiverUrl = _.get(settings, [
'apis',
'project_archiver',
'url',
])
// silently do nothing if project archiver url is not in settings
if (!projectArchiverUrl) {
return
}
metrics.inc('tpds.delete-project')
// send the request directly to project archiver, bypassing third-party-datastore
try {
const response = await request({
uri: `${settings.apis.project_archiver.url}/project/${options.project_id}`,
method: 'delete',
})
return response
} catch (err) {
logger.error(
{ err, project_id: options.project_id },
'error deleting project in third party datastore (project_archiver)'
)
}
}
async function enqueue(group, method, job) {
const tpdsWorkerUrl = _.get(settings, ['apis', 'tpdsworker', 'url'])
// silently do nothing if worker url is not in settings
@ -191,6 +218,7 @@ const TpdsUpdateSender = {
addEntity: callbackify(addEntity),
addFile: callbackify(addFile),
deleteEntity: callbackify(deleteEntity),
deleteProject: callbackify(deleteProject),
enqueue: callbackify(enqueue),
moveEntity: callbackify(moveEntity),
pollDropboxForUser: callbackify(pollDropboxForUser),
@ -199,6 +227,7 @@ const TpdsUpdateSender = {
addEntity,
addFile,
deleteEntity,
deleteProject,
enqueue,
moveEntity,
pollDropboxForUser,

View file

@ -127,6 +127,11 @@ describe('ProjectDeleter', function () {
deleteProject: sinon.stub().resolves(),
},
}
this.TpdsUpdateSender = {
promises: {
deleteProject: sinon.stub().resolves(),
},
}
this.ProjectDeleter = SandboxedModule.require(modulePath, {
requires: {
@ -138,6 +143,7 @@ describe('ProjectDeleter', function () {
.DocumentUpdaterHandler,
'../Tags/TagsHandler': this.TagsHandler,
'../FileStore/FileStoreHandler': this.FileStoreHandler,
'../ThirdPartyDataStore/TpdsUpdateSender': this.TpdsUpdateSender,
'../Collaborators/CollaboratorsHandler': this.CollaboratorsHandler,
'../Collaborators/CollaboratorsGetter': this.CollaboratorsGetter,
'../Docstore/DocstoreManager': this.DocstoreManager,
@ -459,6 +465,14 @@ describe('ProjectDeleter', function () {
this.FileStoreHandler.promises.deleteProject
).to.have.been.calledWith(this.deletedProjects[0].project._id)
})
it('should destroy the files in project-archiver', function () {
expect(
this.TpdsUpdateSender.promises.deleteProject
).to.have.been.calledWith({
project_id: this.deletedProjects[0].project._id,
})
})
})
describe('archiveProject', function () {

View file

@ -20,6 +20,7 @@ const httpPass = 'pass'
const siteUrl = 'http://www.localhost:3000'
const httpAuthSiteUrl = `http://${httpUsername}:${httpPass}@www.localhost:3000`
const filestoreUrl = 'filestore.sharelatex.com'
const projectArchiverUrl = 'project-archiver.overleaf.com'
describe('TpdsUpdateSender', function () {
beforeEach(function () {
@ -358,4 +359,17 @@ describe('TpdsUpdateSender', function () {
job0.json.user_ids[0].should.equal(userId)
})
})
describe('deleteProject', function () {
it('should not call request if there is no project archiver url', async function () {
await this.updateSender.promises.deleteProject({ project_id: projectId })
this.request.should.not.have.been.called
})
it('should make a delete request to project archiver', async function () {
this.settings.apis.project_archiver = { url: projectArchiverUrl }
await this.updateSender.promises.deleteProject({ project_id: projectId })
const { uri, method } = this.request.firstCall.args[0]
method.should.equal('delete')
uri.should.equal(`${projectArchiverUrl}/project/${projectId}`)
})
})
})