CompileManager.coffee 3.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. Settings = require('settings-sharelatex')
  2. redis = require("redis-sharelatex")
  3. rclient = redis.createClient(Settings.redis.web)
  4. DocumentUpdaterHandler = require "../DocumentUpdater/DocumentUpdaterHandler"
  5. Project = require("../../models/Project").Project
  6. ProjectRootDocManager = require "../Project/ProjectRootDocManager"
  7. UserGetter = require "../User/UserGetter"
  8. ClsiManager = require "./ClsiManager"
  9. Metrics = require('../../infrastructure/Metrics')
  10. logger = require("logger-sharelatex")
  11. rateLimiter = require("../../infrastructure/RateLimiter")
  12. module.exports = CompileManager =
  13. compile: (project_id, user_id, options = {}, _callback = (error) ->) ->
  14. timer = new Metrics.Timer("editor.compile")
  15. callback = (args...) ->
  16. timer.done()
  17. _callback(args...)
  18. @_checkIfAutoCompileLimitHasBeenHit options.isAutoCompile, (err, canCompile)->
  19. if !canCompile
  20. return callback null, "autocompile-backoff", []
  21. logger.log project_id: project_id, user_id: user_id, "compiling project"
  22. CompileManager._checkIfRecentlyCompiled project_id, user_id, (error, recentlyCompiled) ->
  23. return callback(error) if error?
  24. if recentlyCompiled
  25. return callback new Error("project was recently compiled so not continuing")
  26. CompileManager._ensureRootDocumentIsSet project_id, (error) ->
  27. return callback(error) if error?
  28. DocumentUpdaterHandler.flushProjectToMongo project_id, (error) ->
  29. return callback(error) if error?
  30. CompileManager.getProjectCompileLimits project_id, (error, limits) ->
  31. return callback(error) if error?
  32. for key, value of limits
  33. options[key] = value
  34. ClsiManager.sendRequest project_id, options, (error, status, outputFiles, output) ->
  35. return callback(error) if error?
  36. logger.log files: outputFiles, "output files"
  37. callback(null, status, outputFiles, output)
  38. getProjectCompileLimits: (project_id, callback = (error, limits) ->) ->
  39. Project.findById project_id, {owner_ref: 1}, (error, project) ->
  40. return callback(error) if error?
  41. UserGetter.getUser project.owner_ref, {"features":1}, (err, owner)->
  42. return callback(error) if error?
  43. callback null, {
  44. timeout: owner.features?.compileTimeout || Settings.defaultFeatures.compileTimeout
  45. compileGroup: owner.features?.compileGroup || Settings.defaultFeatures.compileGroup
  46. }
  47. getLogLines: (project_id, callback)->
  48. Metrics.inc "editor.raw-logs"
  49. ClsiManager.getLogLines project_id, (error, logLines)->
  50. return callback(error) if error?
  51. callback null, logLines
  52. COMPILE_DELAY: 1 # seconds
  53. _checkIfRecentlyCompiled: (project_id, user_id, callback = (error, recentlyCompiled) ->) ->
  54. key = "compile:#{project_id}:#{user_id}"
  55. rclient.set key, true, "EX", @COMPILE_DELAY, "NX", (error, ok) ->
  56. return callback(error) if error?
  57. if ok == "OK"
  58. return callback null, false
  59. else
  60. return callback null, true
  61. _checkIfAutoCompileLimitHasBeenHit: (isAutoCompile, callback = (err, canCompile)->)->
  62. if !isAutoCompile
  63. return callback(null, true)
  64. opts =
  65. endpointName:"auto_compile"
  66. timeInterval:15
  67. subjectName:"everyone"
  68. throttle: 15
  69. rateLimiter.addCount opts, (err, canCompile)->
  70. if err?
  71. canCompile = false
  72. logger.log canCompile:canCompile, opts:opts, "checking if auto compile limit has been hit"
  73. callback err, canCompile
  74. _ensureRootDocumentIsSet: (project_id, callback = (error) ->) ->
  75. Project.findById project_id, 'rootDoc_id', (error, project)=>
  76. return callback(error) if error?
  77. if !project?
  78. return callback new Error("project not found")
  79. if project.rootDoc_id?
  80. callback()
  81. else
  82. ProjectRootDocManager.setRootDocAutomatically project_id, callback