Просмотр исходного кода

Add in DocManager.updateDoc method

James Allen 12 лет назад
Родитель
Сommit
94b25055fc

+ 1 - 0
services/docstore/.gitignore

@@ -2,3 +2,4 @@ node_modules
 app/js/
 app/js/
 test/unit/js
 test/unit/js
 app.js
 app.js
+forever

+ 5 - 1
services/docstore/app.coffee

@@ -4,6 +4,7 @@ logger.initialize("docstore")
 
 
 express = require('express')
 express = require('express')
 HttpController = require "./app/js/HttpController"
 HttpController = require "./app/js/HttpController"
+Errors = require "./app/js/Errors"
 
 
 app = express()
 app = express()
 
 
@@ -14,7 +15,10 @@ app.get '/status', (req, res)->
 
 
 app.use (error, req, res, next) ->
 app.use (error, req, res, next) ->
 	logger.error err: error, "request errored"
 	logger.error err: error, "request errored"
-	res.send(500, "Oops, something went wrong")
+	if error instanceof Errors.NotFoundError
+		res.send 404
+	else
+		res.send(500, "Oops, something went wrong")
 
 
 port = Settings.internal.docstore.port
 port = Settings.internal.docstore.port
 host = Settings.internal.docstore.host
 host = Settings.internal.docstore.host

+ 26 - 4
services/docstore/app/coffee/DocManager.coffee

@@ -1,13 +1,35 @@
 MongoManager = require "./MongoManager"
 MongoManager = require "./MongoManager"
+Errors = require "./Errors"
+logger = require "logger-sharelatex"
+_ = require "underscore"
 
 
 module.exports = DocManager =
 module.exports = DocManager =
-	getDoc: (project_id, doc_id, callback = (error, doc) ->) ->
+	getDoc: (project_id, doc_id, callback = (error, doc, mongoPath) ->) ->
 		MongoManager.findProject project_id, (error, project) ->
 		MongoManager.findProject project_id, (error, project) ->
 			return callback(error) if error?
 			return callback(error) if error?
-			return callback null, null if !project?
-			DocManager.findDocInProject project, doc_id, (error, doc) ->
+			return callback new Errors.NotFoundError("No such project: #{project_id}") if !project?
+			DocManager.findDocInProject project, doc_id, (error, doc, mongoPath) ->
 				return callback(error) if error?
 				return callback(error) if error?
-				return callback null, doc
+				return callback new Errors.NotFoundError("No such doc: #{project_id}") if !doc?
+				return callback null, doc, mongoPath
+
+	updateDoc: (project_id, doc_id, lines, callback = (error) ->) ->
+		DocManager.getDoc project_id, doc_id, (error, doc, mongoPath) ->
+			return callback(error) if error?
+			return callback new Errors.NotFoundError("No such project/doc: #{project_id}/#{doc_id}") if !doc?
+
+			if _.isEqual(doc.lines, lines)
+				logger.log {
+					project_id: project_id, doc_id: doc_id, rev: doc.rev
+				}, "doc lines have not changed"
+				return callback()
+			else
+				logger.log {
+					project_id: project_id, doc_id: doc_id, oldDocLines: doc.lines, newDocLines: lines, rev: doc.rev
+				}, "updating doc lines"
+				MongoManager.updateDoc project_id, mongoPath, lines, (error) ->
+					return callback(error) if error?
+					callback()
 
 
 	findDocInProject: (project, doc_id, callback = (error, doc, mongoPath) ->) ->
 	findDocInProject: (project, doc_id, callback = (error, doc, mongoPath) ->) ->
 		result = @_findDocInFolder project.rootFolder[0], doc_id, "rootFolder.0"
 		result = @_findDocInFolder project.rootFolder[0], doc_id, "rootFolder.0"

+ 10 - 1
services/docstore/app/coffee/MongoManager.coffee

@@ -3,4 +3,13 @@
 module.exports = MongoManager =
 module.exports = MongoManager =
 	findProject: (project_id, callback = (error, project) ->) ->
 	findProject: (project_id, callback = (error, project) ->) ->
 		db.projects.find _id: ObjectId(project_id.toString()), {}, (error, projects = []) ->
 		db.projects.find _id: ObjectId(project_id.toString()), {}, (error, projects = []) ->
-			callback error, projects[0]
+			callback error, projects[0]
+
+	updateDoc: (project_id, docPath, lines, callback = (error) ->) ->
+		update =
+			$set: {}
+			$inc: {}
+		update.$set["#{docPath}.lines"] = lines
+		update.$inc["#{docPath}.rev"] = 1
+
+		db.projects.update _id: ObjectId(project_id), update, callback

+ 2 - 1
services/docstore/package.json

@@ -7,7 +7,8 @@
     "settings-sharelatex": "git+https://github.com/sharelatex/settings-sharelatex.git#master",
     "settings-sharelatex": "git+https://github.com/sharelatex/settings-sharelatex.git#master",
     "logger-sharelatex": "git+https://github.com/sharelatex/logger-sharelatex.git#master",
     "logger-sharelatex": "git+https://github.com/sharelatex/logger-sharelatex.git#master",
     "mongojs": "0.9.11",
     "mongojs": "0.9.11",
-    "express": "~4.1.1"
+    "express": "~4.1.1",
+    "underscore": "~1.6.0"
   },
   },
   "devDependencies": {
   "devDependencies": {
     "grunt-execute": "~0.2.1",
     "grunt-execute": "~0.2.1",

+ 89 - 4
services/docstore/test/unit/coffee/DocManagerTests.coffee

@@ -5,11 +5,13 @@ chai.should()
 expect = chai.expect
 expect = chai.expect
 modulePath = require('path').join __dirname, '../../../app/js/DocManager'
 modulePath = require('path').join __dirname, '../../../app/js/DocManager'
 ObjectId = require("mongojs").ObjectId
 ObjectId = require("mongojs").ObjectId
+Errors = require "../../../app/js/Errors"
 
 
 describe "DocManager", ->
 describe "DocManager", ->
 	beforeEach ->
 	beforeEach ->
 		@DocManager = SandboxedModule.require modulePath, requires:
 		@DocManager = SandboxedModule.require modulePath, requires:
 			"./MongoManager": @MongoManager = {}
 			"./MongoManager": @MongoManager = {}
+			"logger-sharelatex": @logger = {log: sinon.stub()}
 		@doc_id = ObjectId().toString()
 		@doc_id = ObjectId().toString()
 		@project_id = ObjectId().toString()
 		@project_id = ObjectId().toString()
 		@callback = sinon.stub()
 		@callback = sinon.stub()
@@ -19,8 +21,9 @@ describe "DocManager", ->
 			beforeEach -> 
 			beforeEach -> 
 				@project = { name: "mock-project" }
 				@project = { name: "mock-project" }
 				@doc = { _id: @doc_id, lines: ["mock-lines"] }
 				@doc = { _id: @doc_id, lines: ["mock-lines"] }
+				@mongoPath = "mock.mongo.path"
 				@MongoManager.findProject = sinon.stub().callsArgWith(1, null, @project)
 				@MongoManager.findProject = sinon.stub().callsArgWith(1, null, @project)
-				@DocManager.findDocInProject = sinon.stub().callsArgWith(2, null, @doc)
+				@DocManager.findDocInProject = sinon.stub().callsArgWith(2, null, @doc, @mongoPath)
 				@DocManager.getDoc @project_id, @doc_id, @callback
 				@DocManager.getDoc @project_id, @doc_id, @callback
 
 
 			it "should get the project from the database", ->
 			it "should get the project from the database", ->
@@ -34,7 +37,7 @@ describe "DocManager", ->
 					.should.equal true
 					.should.equal true
 
 
 			it "should return the doc", ->
 			it "should return the doc", ->
-				@callback.calledWith(null, @doc).should.equal true
+				@callback.calledWith(null, @doc, @mongoPath).should.equal true
 
 
 		describe "when the project does not exist", ->
 		describe "when the project does not exist", ->
 			beforeEach -> 
 			beforeEach -> 
@@ -45,8 +48,90 @@ describe "DocManager", ->
 			it "should not try to find the doc in the project", ->
 			it "should not try to find the doc in the project", ->
 				@DocManager.findDocInProject.called.should.equal false
 				@DocManager.findDocInProject.called.should.equal false
 
 
-			it "should return null", ->
-				@callback.calledWith(null, null).should.equal true
+			it "should return a NotFoundError", ->
+				@callback
+					.calledWith(new Errors.NotFoundError("No such project: #{@project_id}"))
+					.should.equal true
+
+		describe "when the doc does not exist", ->
+			beforeEach -> 
+				@project = { name: "mock-project" }
+				@MongoManager.findProject = sinon.stub().callsArgWith(1, null, @project)
+				@DocManager.findDocInProject = sinon.stub().callsArgWith(2, null, null, null)
+				@DocManager.getDoc @project_id, @doc_id, @callback
+
+			it "should try to find the doc in the project", ->
+				@DocManager.findDocInProject
+					.calledWith(@project, @doc_id)
+					.should.equal true
+
+			it "should return a NotFoundError", ->
+				@callback
+					.calledWith(new Errors.NotFoundError("No such doc: #{@doc_id}"))
+					.should.equal true
+
+	describe "updateDoc", ->
+		beforeEach ->
+			@oldDocLines = ["old", "doc", "lines"]
+			@newDocLines = ["new", "doc", "lines"]
+			@doc = { _id: @doc_id, lines: @oldDocLines, rev: 42 }
+			@mongoPath = "mock.mongo.path"
+
+			@MongoManager.updateDoc = sinon.stub().callsArg(3)
+
+		describe "when the doc lines have changed", ->
+			beforeEach ->
+				@DocManager.getDoc = sinon.stub().callsArgWith(2, null, @doc, @mongoPath)
+				@DocManager.updateDoc @project_id, @doc_id, @newDocLines, @callback
+
+			it "should get the existing doc", ->
+				@DocManager.getDoc
+					.calledWith(@project_id, @doc_id)
+					.should.equal true
+
+			it "should update the doc with the new doc lines", ->
+				@MongoManager.updateDoc
+					.calledWith(@project_id, @mongoPath, @newDocLines)
+					.should.equal true
+
+			it "should log out the old and new doc lines", ->
+				@logger.log
+					.calledWith(
+						project_id: @project_id
+						doc_id: @doc_id
+						oldDocLines: @oldDocLines
+						newDocLines: @newDocLines
+						rev: @doc.rev
+						"updating doc lines"
+					)
+					.should.equal true
+
+			it "should return the callback", ->
+				@callback.called.should.equal true
+
+		describe "when the doc lines have not changed", ->
+			beforeEach ->
+				@DocManager.getDoc = sinon.stub().callsArgWith(2, null, @doc, @mongoPath)
+				@DocManager.updateDoc @project_id, @doc_id, @oldDocLines.slice(), @callback
+
+			it "should not update the doc", ->
+				@MongoManager.updateDoc.called.should.equal false
+
+			it "should return the callback", ->
+				@callback.called.should.equal true
+
+		describe "when the doc does not exist", ->
+			beforeEach ->
+				@DocManager.getDoc = sinon.stub().callsArgWith(2, null, null, null)
+				@DocManager.updateDoc @project_id, @doc_id, @newDocLines, @callback
+
+			it "should not try to update the doc", ->
+				@MongoManager.updateDoc.called.should.equal false
+
+			it "should return a NotFoundError", ->
+				@callback
+					.calledWith(new Errors.NotFoundError("No such project/doc: #{@project_id}/#{@doc_id}"))
+					.should.equal true
 
 
 	describe "findDocInProject", ->
 	describe "findDocInProject", ->
 		it "should find the doc when it is in the root folder", (done) ->
 		it "should find the doc when it is in the root folder", (done) ->

+ 25 - 0
services/docstore/test/unit/coffee/MongoManagerTests.coffee

@@ -25,3 +25,28 @@ describe "MongoManager", ->
 					_id: ObjectId(@project_id)
 					_id: ObjectId(@project_id)
 				}, {})
 				}, {})
 				.should.equal true
 				.should.equal true
+
+		it "should call the callback with the project", ->
+			@callback.calledWith(null, @project).should.equal true
+
+	describe "updateDoc", ->
+		beforeEach ->
+			@lines = ["mock-lines"]
+			@docPath = "rootFolder.0.folders.1.docs.0"
+			@db.projects.update = sinon.stub().callsArg(2)
+			@MongoManager.updateDoc @project_id, @docPath, @lines, @callback
+
+		it "should update the doc lines and increment the TPDS rev", ->
+			@db.projects.update
+				.calledWith({
+					_id: ObjectId(@project_id)
+				}, {
+					$set:
+						"rootFolder.0.folders.1.docs.0.lines": @lines
+					$inc:
+						"rootFolder.0.folders.1.docs.0.rev": 1
+				})
+				.should.equal true
+
+		it "should call the callback with the project", ->
+			@callback.called.should.equal true