mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -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}")
|
error = new Error("project-history returned a non-success status code: #{res.statusCode}")
|
||||||
callback error
|
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) ->) ->
|
injectUserDetails: (data, callback = (error, data_with_users) ->) ->
|
||||||
# data can be either:
|
# 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