mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-29 16:33:39 -05:00
dab6e9aa8e
The unconventional use of callbacks to return both an error and data after compilation created a subtle bug where the output files were dropped by the LockManager in case of an error such as a timeout. This prevented the frontend to show error logs when a timeout occurs, creating confusion among users. We now attach the output files to the error so that they reach the controller and are sent back to the web service.
119 lines
4.1 KiB
CoffeeScript
119 lines
4.1 KiB
CoffeeScript
RequestParser = require "./RequestParser"
|
|
CompileManager = require "./CompileManager"
|
|
Settings = require "settings-sharelatex"
|
|
Metrics = require "./Metrics"
|
|
ProjectPersistenceManager = require "./ProjectPersistenceManager"
|
|
logger = require "logger-sharelatex"
|
|
Errors = require "./Errors"
|
|
|
|
module.exports = CompileController =
|
|
compile: (req, res, next = (error) ->) ->
|
|
timer = new Metrics.Timer("compile-request")
|
|
RequestParser.parse req.body, (error, request) ->
|
|
return next(error) if error?
|
|
request.project_id = req.params.project_id
|
|
request.user_id = req.params.user_id if req.params.user_id?
|
|
ProjectPersistenceManager.markProjectAsJustAccessed request.project_id, (error) ->
|
|
return next(error) if error?
|
|
CompileManager.doCompileWithLock request, (error, outputFiles = []) ->
|
|
if error instanceof Errors.AlreadyCompilingError
|
|
code = 423 # Http 423 Locked
|
|
status = "compile-in-progress"
|
|
else if error instanceof Errors.FilesOutOfSyncError
|
|
code = 409 # Http 409 Conflict
|
|
status = "retry"
|
|
else if error?.terminated
|
|
status = "terminated"
|
|
else if error?.validate
|
|
status = "validation-#{error.validate}"
|
|
else if error?.timedout
|
|
status = "timedout"
|
|
logger.log err: error, project_id: request.project_id, "timeout running compile"
|
|
else if error?
|
|
status = "error"
|
|
code = 500
|
|
logger.warn err: error, project_id: request.project_id, "error running compile"
|
|
else
|
|
status = "failure"
|
|
for file in outputFiles
|
|
if file.path?.match(/output\.pdf$/)
|
|
status = "success"
|
|
|
|
if status == "failure"
|
|
logger.warn project_id: request.project_id, outputFiles:outputFiles, "project failed to compile successfully, no output.pdf generated"
|
|
|
|
# log an error if any core files are found
|
|
for file in outputFiles
|
|
if file.path is "core"
|
|
logger.error project_id:request.project_id, req:req, outputFiles:outputFiles, "core file found in output"
|
|
|
|
if error?
|
|
outputFiles = error.outputFiles || []
|
|
|
|
timer.done()
|
|
res.status(code or 200).send {
|
|
compile:
|
|
status: status
|
|
error: error?.message or error
|
|
outputFiles: outputFiles.map (file) ->
|
|
url:
|
|
"#{Settings.apis.clsi.url}/project/#{request.project_id}" +
|
|
(if request.user_id? then "/user/#{request.user_id}" else "") +
|
|
(if file.build? then "/build/#{file.build}" else "") +
|
|
"/output/#{file.path}"
|
|
path: file.path
|
|
type: file.type
|
|
build: file.build
|
|
}
|
|
|
|
stopCompile: (req, res, next) ->
|
|
{project_id, user_id} = req.params
|
|
CompileManager.stopCompile project_id, user_id, (error) ->
|
|
return next(error) if error?
|
|
res.sendStatus(204)
|
|
|
|
clearCache: (req, res, next = (error) ->) ->
|
|
ProjectPersistenceManager.clearProject req.params.project_id, req.params.user_id, (error) ->
|
|
return next(error) if error?
|
|
res.sendStatus(204) # No content
|
|
|
|
syncFromCode: (req, res, next = (error) ->) ->
|
|
file = req.query.file
|
|
line = parseInt(req.query.line, 10)
|
|
column = parseInt(req.query.column, 10)
|
|
project_id = req.params.project_id
|
|
user_id = req.params.user_id
|
|
CompileManager.syncFromCode project_id, user_id, file, line, column, (error, pdfPositions) ->
|
|
return next(error) if error?
|
|
res.json {
|
|
pdf: pdfPositions
|
|
}
|
|
|
|
syncFromPdf: (req, res, next = (error) ->) ->
|
|
page = parseInt(req.query.page, 10)
|
|
h = parseFloat(req.query.h)
|
|
v = parseFloat(req.query.v)
|
|
project_id = req.params.project_id
|
|
user_id = req.params.user_id
|
|
CompileManager.syncFromPdf project_id, user_id, page, h, v, (error, codePositions) ->
|
|
return next(error) if error?
|
|
res.json {
|
|
code: codePositions
|
|
}
|
|
|
|
wordcount: (req, res, next = (error) ->) ->
|
|
file = req.query.file || "main.tex"
|
|
project_id = req.params.project_id
|
|
user_id = req.params.user_id
|
|
image = req.query.image
|
|
logger.log {image, file, project_id}, "word count request"
|
|
|
|
CompileManager.wordcount project_id, user_id, file, image, (error, result) ->
|
|
return next(error) if error?
|
|
res.json {
|
|
texcount: result
|
|
}
|
|
|
|
status: (req, res, next = (error)-> )->
|
|
res.send("OK")
|
|
|