HealthCheckController.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /* eslint-disable
  2. handle-callback-err,
  3. max-len,
  4. no-path-concat,
  5. no-unused-vars,
  6. node/no-deprecated-api,
  7. */
  8. // TODO: This file was created by bulk-decaffeinate.
  9. // Fix any style issues and re-enable lint.
  10. /*
  11. * decaffeinate suggestions:
  12. * DS102: Remove unnecessary code created because of implicit returns
  13. * DS207: Consider shorter variations of null checks
  14. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  15. */
  16. let HealthCheckController
  17. const Mocha = require('mocha')
  18. const Base = require('mocha/lib/reporters/base')
  19. const RedisWrapper = require('../../infrastructure/RedisWrapper')
  20. const rclient = RedisWrapper.client('health_check')
  21. const settings = require('settings-sharelatex')
  22. const logger = require('logger-sharelatex')
  23. const domain = require('domain')
  24. const UserGetter = require('../User/UserGetter')
  25. module.exports = HealthCheckController = {
  26. check(req, res, next) {
  27. if (next == null) {
  28. next = function(error) {}
  29. }
  30. const d = domain.create()
  31. d.on('error', error => logger.err({ err: error }, 'error in mocha'))
  32. return d.run(function() {
  33. const mocha = new Mocha({ reporter: Reporter(res), timeout: 10000 })
  34. mocha.addFile('test/smoke/src/SmokeTests.js')
  35. return mocha.run(function() {
  36. // TODO: combine this with the smoke-test-sharelatex module
  37. // we need to clean up all references to the smokeTest module
  38. // so it can be garbage collected. The only reference should
  39. // be in its parent, when it is loaded by mocha.addFile.
  40. const path = require.resolve(
  41. __dirname + '/../../../../test/smoke/src/SmokeTests.js'
  42. )
  43. const smokeTestModule = require.cache[path]
  44. if (smokeTestModule != null) {
  45. let idx
  46. const { parent } = smokeTestModule
  47. while ((idx = parent.children.indexOf(smokeTestModule)) !== -1) {
  48. parent.children.splice(idx, 1)
  49. }
  50. } else {
  51. logger.warn({ path }, 'smokeTestModule not defined')
  52. }
  53. // remove the smokeTest from the module cache
  54. return delete require.cache[path]
  55. })
  56. })
  57. },
  58. checkActiveHandles(req, res, next) {
  59. if (!(settings.maxActiveHandles > 0) || !process._getActiveHandles) {
  60. return next()
  61. }
  62. const activeHandlesCount = (process._getActiveHandles() || []).length
  63. if (activeHandlesCount > settings.maxActiveHandles) {
  64. logger.err(
  65. { activeHandlesCount, maxActiveHandles: settings.maxActiveHandles },
  66. 'exceeded max active handles, failing health check'
  67. )
  68. return res.sendStatus(500)
  69. } else {
  70. logger.debug(
  71. { activeHandlesCount, maxActiveHandles: settings.maxActiveHandles },
  72. 'active handles are below maximum'
  73. )
  74. next()
  75. }
  76. },
  77. checkApi(req, res, next) {
  78. rclient.healthCheck(err => {
  79. if (err) {
  80. logger.err({ err }, 'failed api redis health check')
  81. return res.sendStatus(500)
  82. }
  83. UserGetter.getUserEmail(settings.smokeTest.userId, (err, email) => {
  84. if (err) {
  85. logger.err({ err }, 'failed api mongo health check')
  86. return res.sendStatus(500)
  87. }
  88. if (email == null) {
  89. logger.err({ err }, 'failed api mongo health check (no email)')
  90. return res.sendStatus(500)
  91. }
  92. res.sendStatus(200)
  93. })
  94. })
  95. },
  96. checkRedis(req, res, next) {
  97. return rclient.healthCheck(function(error) {
  98. if (error != null) {
  99. logger.err({ err: error }, 'failed redis health check')
  100. return res.sendStatus(500)
  101. } else {
  102. return res.sendStatus(200)
  103. }
  104. })
  105. },
  106. checkMongo(req, res, next) {
  107. return UserGetter.getUserEmail(settings.smokeTest.userId, function(
  108. err,
  109. email
  110. ) {
  111. if (err != null) {
  112. logger.err({ err }, 'mongo health check failed, error present')
  113. return res.sendStatus(500)
  114. } else if (email == null) {
  115. logger.err(
  116. { err },
  117. 'mongo health check failed, no emai present in find result'
  118. )
  119. return res.sendStatus(500)
  120. } else {
  121. return res.sendStatus(200)
  122. }
  123. })
  124. }
  125. }
  126. var Reporter = res =>
  127. function(runner) {
  128. Base.call(this, runner)
  129. const tests = []
  130. const passes = []
  131. const failures = []
  132. runner.on('test end', test => tests.push(test))
  133. runner.on('pass', test => passes.push(test))
  134. runner.on('fail', test => failures.push(test))
  135. return runner.on('end', () => {
  136. const clean = test => ({
  137. title: test.fullTitle(),
  138. duration: test.duration,
  139. err: test.err,
  140. timedOut: test.timedOut
  141. })
  142. const results = {
  143. stats: this.stats,
  144. failures: failures.map(clean),
  145. passes: passes.map(clean)
  146. }
  147. res.contentType('application/json')
  148. if (failures.length > 0) {
  149. logger.err({ failures }, 'health check failed')
  150. return res.status(500).send(JSON.stringify(results, null, 2))
  151. } else {
  152. return res.status(200).send(JSON.stringify(results, null, 2))
  153. }
  154. })
  155. }