mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-07 20:31:06 -05:00
Merge pull request #1040 from sharelatex/bg-start-history-in-v2-for-old-projects
allow creating v2 history for existing project without v2 history GitOrigin-RevId: 2ccbe55f5c203c37d37be00306de5e265555f909
This commit is contained in:
parent
3d94be22b1
commit
707a258d5b
3 changed files with 158 additions and 0 deletions
|
@ -27,6 +27,17 @@ module.exports = HistoryManager =
|
|||
error = new Error("project-history returned a non-success status code: #{res.statusCode}")
|
||||
callback error
|
||||
|
||||
flushProject: (project_id, callback = (error) ->) ->
|
||||
request.post {
|
||||
url: "#{settings.apis.project_history.url}/project/#{project_id}/flush"
|
||||
}, (error, res, body)->
|
||||
return callback(error) if error?
|
||||
if res.statusCode >= 200 and res.statusCode < 300
|
||||
callback()
|
||||
else
|
||||
error = new Error("project-history returned a non-success status code: #{res.statusCode}")
|
||||
callback error
|
||||
|
||||
injectUserDetails: (data, callback = (error, data_with_users) ->) ->
|
||||
# data can be either:
|
||||
# {
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
Project = require('../../models/Project').Project
|
||||
ProjectDetailsHandler = require "./ProjectDetailsHandler"
|
||||
logger = require('logger-sharelatex')
|
||||
settings = require("settings-sharelatex")
|
||||
HistoryManager = require "../History/HistoryManager"
|
||||
ProjectEntityUpdateHandler = require "./ProjectEntityUpdateHandler"
|
||||
|
||||
module.exports = ProjectHistoryHandler =
|
||||
|
||||
setHistoryId: (project_id, history_id, callback = (err) ->) ->
|
||||
# reject invalid history ids
|
||||
return callback(new Error("invalid history id")) if !history_id or typeof(history_id) isnt 'number'
|
||||
# use $exists:false to prevent overwriting any existing history id, atomically
|
||||
Project.update {_id: project_id, "overleaf.history.id": {$exists:false}}, {"overleaf.history.id":history_id}, (err, result)->
|
||||
return callback(err) if err?
|
||||
return callback(new Error("history exists")) if result?.n == 0
|
||||
callback()
|
||||
|
||||
getHistoryId: (project_id, callback = (err, result) ->) ->
|
||||
ProjectDetailsHandler.getDetails project_id, (err, project) ->
|
||||
return callback(err) if err? # n.b. getDetails returns an error if the project doesn't exist
|
||||
return callback(new Error("history exists")) if project.overleaf?.history?.id?
|
||||
callback(null, project?.overleaf?.history?.id)
|
||||
|
||||
ensureHistoryExistsForProject: (project_id, callback = (err) ->) ->
|
||||
# We can only set a history id for a project that doesn't have one. The
|
||||
# history id is cached in the project history service, and changing an
|
||||
# existing value corrupts the history, leaving it in an irrecoverable
|
||||
# state. Setting a history id when one wasn't present before is ok,
|
||||
# because undefined history ids aren't cached.
|
||||
ProjectHistoryHandler.getHistoryId project_id, (err, history_id) ->
|
||||
return callback(err) if err?
|
||||
return callback() if history_id? # history already exists, success
|
||||
HistoryManager.initializeProject (err, history) ->
|
||||
return callback(err) if err?
|
||||
return callback(new Error("failed to initialize history id")) if !history?.overleaf_id
|
||||
ProjectHistoryHandler.setHistoryId project_id, history.overleaf_id, (err) ->
|
||||
return callback(err) if err?
|
||||
ProjectEntityUpdateHandler.resyncProjectHistory project_id, (err) ->
|
||||
return callback(err) if err?
|
||||
logger.log {project_id: project_id, history_id: history.overleaf_id}, "started syncing project with new history id"
|
||||
HistoryManager.flushProject project_id, callback
|
|
@ -0,0 +1,105 @@
|
|||
chai = require('chai')
|
||||
assert = require('chai').assert
|
||||
should = chai.should()
|
||||
expect = chai.expect
|
||||
sinon = require 'sinon'
|
||||
modulePath = "../../../../app/js/Features/Project/ProjectHistoryHandler"
|
||||
SandboxedModule = require('sandboxed-module')
|
||||
ObjectId = require("mongoose").Types.ObjectId
|
||||
|
||||
describe 'ProjectHistoryHandler', ->
|
||||
project_id = '4eecb1c1bffa66588e0000a1'
|
||||
userId = 1234
|
||||
|
||||
beforeEach ->
|
||||
@ProjectModel = class Project
|
||||
constructor:(options)->
|
||||
@._id = project_id
|
||||
@name = "project_name_here"
|
||||
@rev = 0
|
||||
rootFolder:[@rootFolder]
|
||||
@project = new @ProjectModel()
|
||||
|
||||
@callback = sinon.stub()
|
||||
|
||||
@ProjectHistoryHandler = SandboxedModule.require modulePath, requires:
|
||||
'logger-sharelatex': @logger = {log:sinon.stub(), error: sinon.stub(), err:->}
|
||||
'settings-sharelatex': @Settings = {}
|
||||
'../../models/Project': Project:@ProjectModel
|
||||
'./ProjectDetailsHandler': @ProjectDetailsHandler = {}
|
||||
'../History/HistoryManager': @HistoryManager = {}
|
||||
'./ProjectEntityUpdateHandler': @ProjectEntityUpdateHandler = {}
|
||||
|
||||
describe "starting history for an existing project", ->
|
||||
beforeEach ->
|
||||
@newHistoryId = 123456789
|
||||
@HistoryManager.initializeProject = sinon.stub().callsArgWith(0, null, {overleaf_id: @newHistoryId})
|
||||
@HistoryManager.flushProject = sinon.stub().callsArg(1)
|
||||
@ProjectEntityUpdateHandler.resyncProjectHistory = sinon.stub().callsArg(1)
|
||||
|
||||
describe "when the history does not already exist", ->
|
||||
beforeEach ->
|
||||
@ProjectDetailsHandler.getDetails = sinon.stub().withArgs(project_id).callsArgWith(1, null, @project)
|
||||
@ProjectModel.update = sinon.stub().callsArgWith(2,null,{n:1})
|
||||
@ProjectHistoryHandler.ensureHistoryExistsForProject project_id, @callback
|
||||
|
||||
it "should get any existing history id for the project", ->
|
||||
@ProjectDetailsHandler.getDetails
|
||||
.calledWith(project_id)
|
||||
.should.equal true
|
||||
|
||||
it "should initialize a new history in the v1 history service", ->
|
||||
@HistoryManager.initializeProject
|
||||
.called.should.equal.true
|
||||
|
||||
it "should set the new history id on the project", ->
|
||||
@ProjectModel.update
|
||||
.calledWith({_id: project_id, "overleaf.history.id": {$exists:false}}, {"overleaf.history.id":@newHistoryId})
|
||||
.should.equal true
|
||||
|
||||
it "should resync the project history", ->
|
||||
@ProjectEntityUpdateHandler.resyncProjectHistory
|
||||
.calledWith(project_id)
|
||||
.should.equal true
|
||||
|
||||
it "should flush the project history", ->
|
||||
@HistoryManager.flushProject
|
||||
.calledWith(project_id)
|
||||
.should.equal true
|
||||
|
||||
it "should call the callback without an error", ->
|
||||
@callback.called.should.equal true
|
||||
|
||||
describe "when the history already exists", ->
|
||||
beforeEach ->
|
||||
@project.overleaf = {history: {id: 1234}}
|
||||
@ProjectDetailsHandler.getDetails = sinon.stub().withArgs(project_id).callsArgWith(1, null, @project)
|
||||
@ProjectModel.update = sinon.stub()
|
||||
@ProjectHistoryHandler.ensureHistoryExistsForProject project_id, @callback
|
||||
|
||||
it "should get any existing history id for the project", ->
|
||||
@ProjectDetailsHandler.getDetails
|
||||
.calledWith(project_id)
|
||||
.should.equal true
|
||||
|
||||
it "should not initialize a new history in the v1 history service", ->
|
||||
@HistoryManager.initializeProject
|
||||
.called.should.equal false
|
||||
|
||||
it "should not set the new history id on the project", ->
|
||||
@ProjectModel.update
|
||||
.called
|
||||
.should.equal false
|
||||
|
||||
it "should not resync the project history", ->
|
||||
@ProjectEntityUpdateHandler.resyncProjectHistory
|
||||
.called
|
||||
.should.equal false
|
||||
|
||||
it "should not flush the project history", ->
|
||||
@HistoryManager.flushProject
|
||||
.called
|
||||
.should.equal false
|
||||
|
||||
it "should call the callback", ->
|
||||
@callback.calledWith().should.equal true
|
Loading…
Reference in a new issue