Procházet zdrojové kódy

Add in mongo health check end point

James Allen před 11 roky
rodič
revize
03e9d7390f

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

@@ -9,6 +9,7 @@ DispatchManager = require('./app/js/DispatchManager')
 Keys = require('./app/js/RedisKeyBuilder')
 Keys = require('./app/js/RedisKeyBuilder')
 Errors = require "./app/js/Errors"
 Errors = require "./app/js/Errors"
 HttpController = require "./app/js/HttpController"
 HttpController = require "./app/js/HttpController"
+MongoHealthCheck = require('./app/js/MongoHealthCheck')
 
 
 redis = require("redis-sharelatex")
 redis = require("redis-sharelatex")
 rclient = redis.createClient(Settings.redis.web)
 rclient = redis.createClient(Settings.redis.web)
@@ -57,6 +58,12 @@ app.get '/status', (req, res)->
 	else
 	else
 		res.send('document updater is alive')
 		res.send('document updater is alive')
 
 
+app.get '/health_check/mongo', (req, res, next) ->
+	MongoHealthCheck.isAlive (error) ->
+		if error?
+			res.send 500, error.message
+		else
+			res.send 200
 
 
 redisCheck = require("redis-sharelatex").activeHealthCheckRedis(Settings.redis.web)
 redisCheck = require("redis-sharelatex").activeHealthCheckRedis(Settings.redis.web)
 app.get "/health_check/redis", (req, res, next)->
 app.get "/health_check/redis", (req, res, next)->

+ 26 - 0
services/document-updater/app/coffee/MongoHealthCheck.coffee

@@ -0,0 +1,26 @@
+Settings = require "settings-sharelatex"
+PersistenceManager = require "./PersistenceManager"
+
+module.exports = MongoHealthCheck =
+	isAlive: (_callback = (error) ->) ->
+		# We've seen very occasionally the doc-updater losing its connection to Mongo.
+		# E.g. https://sharelatex.hackpad.com/29th-Aug-2015-0650-0740-fHlw8RL8zuN
+		# It seems that the mongo callbacks never returned.
+		# Mongo is only called in the persistence manager, so we do a read-only
+		# test call, check that it's working, and returns in a reasonable time.
+		callback = (args...) ->
+			_callback(args...)
+			_callback = () ->
+
+		doc_id = Settings.smokeTest?.doc_id
+		if !doc_id?
+			return callback(new Error("No test doc_id configured"))
+
+		PersistenceManager.getDocVersionInMongo doc_id, (error, version) ->
+			return callback(error) if error?
+			callback(null)
+
+		timeout = Settings.smokeTest?.timeout or 10000
+		setTimeout () ->
+			callback(new Error("Mongo did not return in #{timeout}ms"))
+		, timeout

+ 52 - 0
services/document-updater/test/unit/coffee/MongoHealthCheckTests/MongoHealthCheckTests.coffee

@@ -0,0 +1,52 @@
+SandboxedModule = require('sandboxed-module')
+sinon = require('sinon')
+require('chai').should()
+modulePath = require('path').join __dirname, '../../../../app/js/MongoHealthCheck'
+
+describe "MongoHealthCheck", ->
+	beforeEach ->
+		@MongoHealthCheck = SandboxedModule.require modulePath, requires:
+			"settings-sharelatex": @Settings = {}
+			"./PersistenceManager": @PersistenceManager = {}
+		@doc_id = "mock-doc-id"
+		@callback = sinon.stub()
+
+	describe "isAlive", ->
+		describe "with no configured doc_id", ->
+			beforeEach ->
+				@MongoHealthCheck.isAlive @callback
+			
+			it "should call the call the callback with an error", ->
+				@callback.calledOnce.should.equal true
+				error = @callback.args[0][0]
+				error.message.should.equal "No test doc_id configured"
+			
+		describe "when mongo returns within the timeout", ->
+			beforeEach ->
+				@Settings.smokeTest =
+					doc_id: @doc_id
+				@PersistenceManager.getDocVersionInMongo = sinon.stub().callsArg(1)
+				@MongoHealthCheck.isAlive @callback
+			
+			it "should call PersistenceManager.getDocVersionInMongo", ->
+				@PersistenceManager.getDocVersionInMongo
+					.calledWith(@doc_id)
+					.should.equal true
+			
+			it "should call the call the callback without an error", ->
+				@callback.calledOnce.should.equal true
+				@callback.calledWith(null).should.equal true
+			
+		describe "when mongo does not return within the timeout", ->
+			beforeEach (done) ->
+				@Settings.smokeTest =
+					doc_id: @doc_id
+					timeout: 50
+				@PersistenceManager.getDocVersionInMongo = (doc_id, callback) ->
+					setTimeout callback, 100
+				@MongoHealthCheck.isAlive (@error) =>
+					done()
+			
+			it "should call the call the callback with an error", ->
+				@error.message.should.equal "Mongo did not return in 50ms"
+