فهرست منبع

Don't let HTTP calls take longer than 5 seconds since we're inside a 30 second lock

James Allen 10 سال پیش
والد
کامیت
6c79ab4321

+ 7 - 0
services/document-updater/app/coffee/PersistenceManager.coffee

@@ -5,6 +5,11 @@ Metrics = require "./Metrics"
 {db, ObjectId} = require("./mongojs")
 logger = require "logger-sharelatex"
 
+# We have to be quick with HTTP calls because we're holding a lock that
+# expires after 30 seconds. We can't let any errors in the rest of the stack
+# hold us up, and need to bail out quickly if there is a problem.
+MAX_HTTP_REQUEST_LENGTH = 5000 # 5 seconds
+
 module.exports = PersistenceManager =
 	getDoc: (project_id, doc_id, callback = (error, lines, version) ->) ->
 		PersistenceManager.getDocFromWeb project_id, doc_id, (error, lines) ->
@@ -37,6 +42,7 @@ module.exports = PersistenceManager =
 				pass: Settings.apis.web.pass
 				sendImmediately: true
 			jar: false
+			timeout: MAX_HTTP_REQUEST_LENGTH
 		}, (error, res, body) ->
 			return callback(error) if error?
 			if res.statusCode >= 200 and res.statusCode < 300
@@ -69,6 +75,7 @@ module.exports = PersistenceManager =
 				pass: Settings.apis.web.pass
 				sendImmediately: true
 			jar: false
+			timeout: MAX_HTTP_REQUEST_LENGTH
 		}, (error, res, body) ->
 			return callback(error) if error?
 			if res.statusCode >= 200 and res.statusCode < 300

+ 28 - 0
services/document-updater/test/acceptance/coffee/FlushingDocsTests.coffee

@@ -1,6 +1,7 @@
 sinon = require "sinon"
 chai = require("chai")
 chai.should()
+expect = chai.expect
 async = require "async"
 {db, ObjectId} = require "../../../app/js/mongojs"
 
@@ -71,3 +72,30 @@ describe "Flushing a doc to Mongo", ->
 		it "should not flush the doc to the web api", ->
 			MockWebApi.setDocumentLines.called.should.equal false
 
+	describe "when the web api http request takes a long time", ->
+		before (done) ->
+			[@project_id, @doc_id] = [DocUpdaterClient.randomId(), DocUpdaterClient.randomId()]
+			@timeout = 10000
+			MockWebApi.insertDoc @project_id, @doc_id, {
+				lines: @lines
+			}
+			sinon.stub MockWebApi, "setDocumentLines", (project_id, doc_id, lines, callback = (error) ->) ->
+				setTimeout callback, 30000
+
+			db.docOps.insert {
+				doc_id: ObjectId(@doc_id)
+				version: @version
+			}, (error) =>
+				throw error if error?
+				DocUpdaterClient.preloadDoc @project_id, @doc_id, done
+
+		after ->
+			MockWebApi.setDocumentLines.restore()
+		
+		it "should return quickly(ish)", (done) ->
+			start = Date.now()
+			DocUpdaterClient.flushDoc @project_id, @doc_id, (error, res, doc) =>
+				res.statusCode.should.equal 500
+				delta = Date.now() - start
+				expect(delta).to.be.below 20000
+				done()

+ 18 - 2
services/document-updater/test/acceptance/coffee/GettingADocumentTests.coffee

@@ -1,6 +1,7 @@
 sinon = require "sinon"
 chai = require("chai")
 chai.should()
+expect = chai.expect
 {db, ObjectId} = require "../../../app/js/mongojs"
 
 MockWebApi = require "./helpers/MockWebApi"
@@ -113,7 +114,22 @@ describe "Getting a document", ->
 		it "should return 500", ->
 			@statusCode.should.equal 500
 
+	describe "when the web api http request takes a long time", ->
+		before (done) ->
+			@timeout = 10000
+			[@project_id, @doc_id] = [DocUpdaterClient.randomId(), DocUpdaterClient.randomId()]
+			sinon.stub MockWebApi, "getDocument", (project_id, doc_id, callback = (error, doc) ->) ->
+				setTimeout callback, 30000
+			done()
 
-
-
+		after ->
+			MockWebApi.getDocument.restore()
+		
+		it "should return quickly(ish)", (done) ->
+			start = Date.now()
+			DocUpdaterClient.getDoc @project_id, @doc_id, (error, res, doc) =>
+				res.statusCode.should.equal 500
+				delta = Date.now() - start
+				expect(delta).to.be.below 20000
+				done()
 

+ 1 - 0
services/document-updater/test/unit/coffee/PersistenceManager/getDocFromWebTests.coffee

@@ -41,6 +41,7 @@ describe "PersistenceManager.getDocFromWeb", ->
 						pass: @pass
 						sendImmediately: true
 					jar: false
+					timeout: 5000
 				})
 				.should.equal true
 

+ 1 - 0
services/document-updater/test/unit/coffee/PersistenceManager/setDocInWebTests.coffee

@@ -43,6 +43,7 @@ describe "PersistenceManager.setDocInWeb", ->
 						pass: @pass
 						sendImmediately: true
 					jar: false
+					timeout: 5000
 				})
 				.should.equal true