2014-02-12 10:40:42 +00:00
|
|
|
Settings = require "settings-sharelatex"
|
|
|
|
Errors = require "./Errors"
|
|
|
|
Metrics = require "./Metrics"
|
2014-05-14 13:16:27 +00:00
|
|
|
logger = require "logger-sharelatex"
|
2017-07-18 14:28:18 +00:00
|
|
|
request = (require("requestretry")).defaults({
|
|
|
|
maxAttempts: 2
|
|
|
|
retryDelay: 10
|
|
|
|
})
|
2014-02-12 10:40:42 +00:00
|
|
|
|
2016-04-12 16:10:39 +00:00
|
|
|
# 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
|
|
|
|
|
2020-01-14 13:53:50 +00:00
|
|
|
updateMetric = (method, error, response) ->
|
|
|
|
# find the status, with special handling for connection timeouts
|
|
|
|
# https://github.com/request/request#timeouts
|
|
|
|
status = if error?.connect is true
|
|
|
|
"#{error.code} (connect)"
|
|
|
|
else if error?
|
|
|
|
error.code
|
|
|
|
else if response?
|
|
|
|
response.statusCode
|
2020-01-14 15:00:21 +00:00
|
|
|
Metrics.inc method, 1, {status: status}
|
|
|
|
if error?.attempts > 1
|
|
|
|
Metrics.inc "#{method}-retries", 1, {status: 'error'}
|
|
|
|
if response?.attempts > 1
|
|
|
|
Metrics.inc "#{method}-retries", 1, {status: 'success'}
|
2020-01-14 13:53:50 +00:00
|
|
|
|
2014-02-12 10:40:42 +00:00
|
|
|
module.exports = PersistenceManager =
|
2019-11-15 16:53:16 +00:00
|
|
|
getDoc: (project_id, doc_id, _callback = (error, lines, version, ranges, pathname, projectHistoryId, projectHistoryType) ->) ->
|
2014-02-12 10:40:42 +00:00
|
|
|
timer = new Metrics.Timer("persistenceManager.getDoc")
|
|
|
|
callback = (args...) ->
|
|
|
|
timer.done()
|
|
|
|
_callback(args...)
|
|
|
|
|
|
|
|
url = "#{Settings.apis.web.url}/project/#{project_id}/doc/#{doc_id}"
|
|
|
|
request {
|
|
|
|
url: url
|
|
|
|
method: "GET"
|
|
|
|
headers:
|
|
|
|
"accept": "application/json"
|
|
|
|
auth:
|
|
|
|
user: Settings.apis.web.user
|
|
|
|
pass: Settings.apis.web.pass
|
|
|
|
sendImmediately: true
|
|
|
|
jar: false
|
2016-04-12 16:10:39 +00:00
|
|
|
timeout: MAX_HTTP_REQUEST_LENGTH
|
2014-02-12 10:40:42 +00:00
|
|
|
}, (error, res, body) ->
|
2020-01-14 13:53:50 +00:00
|
|
|
updateMetric('getDoc', error, res)
|
2014-02-12 10:40:42 +00:00
|
|
|
return callback(error) if error?
|
|
|
|
if res.statusCode >= 200 and res.statusCode < 300
|
|
|
|
try
|
|
|
|
body = JSON.parse body
|
|
|
|
catch e
|
|
|
|
return callback(e)
|
2016-11-29 17:13:16 +00:00
|
|
|
if !body.lines?
|
|
|
|
return callback(new Error("web API response had no doc lines"))
|
|
|
|
if !body.version? or not body.version instanceof Number
|
|
|
|
return callback(new Error("web API response had no valid doc version"))
|
2018-03-02 10:02:49 +00:00
|
|
|
if !body.pathname?
|
|
|
|
return callback(new Error("web API response had no valid doc pathname"))
|
2019-11-15 16:53:16 +00:00
|
|
|
return callback null, body.lines, body.version, body.ranges, body.pathname, body.projectHistoryId, body.projectHistoryType
|
2014-02-12 10:40:42 +00:00
|
|
|
else if res.statusCode == 404
|
|
|
|
return callback(new Errors.NotFoundError("doc not not found: #{url}"))
|
|
|
|
else
|
|
|
|
return callback(new Error("error accessing web API: #{url} #{res.statusCode}"))
|
|
|
|
|
2019-04-23 00:02:48 +00:00
|
|
|
setDoc: (project_id, doc_id, lines, version, ranges, lastUpdatedAt, lastUpdatedBy,_callback = (error) ->) ->
|
2014-02-12 10:40:42 +00:00
|
|
|
timer = new Metrics.Timer("persistenceManager.setDoc")
|
|
|
|
callback = (args...) ->
|
|
|
|
timer.done()
|
|
|
|
_callback(args...)
|
|
|
|
|
|
|
|
url = "#{Settings.apis.web.url}/project/#{project_id}/doc/#{doc_id}"
|
|
|
|
request {
|
|
|
|
url: url
|
|
|
|
method: "POST"
|
2016-12-01 16:40:15 +00:00
|
|
|
json:
|
2014-02-12 10:40:42 +00:00
|
|
|
lines: lines
|
2016-12-08 12:31:43 +00:00
|
|
|
ranges: ranges
|
2016-11-29 17:06:23 +00:00
|
|
|
version: version
|
2019-04-23 00:02:48 +00:00
|
|
|
lastUpdatedBy: lastUpdatedBy
|
|
|
|
lastUpdatedAt: lastUpdatedAt
|
2014-02-12 10:40:42 +00:00
|
|
|
auth:
|
|
|
|
user: Settings.apis.web.user
|
|
|
|
pass: Settings.apis.web.pass
|
|
|
|
sendImmediately: true
|
|
|
|
jar: false
|
2016-04-12 16:10:39 +00:00
|
|
|
timeout: MAX_HTTP_REQUEST_LENGTH
|
2014-02-12 10:40:42 +00:00
|
|
|
}, (error, res, body) ->
|
2020-01-14 13:53:50 +00:00
|
|
|
updateMetric('setDoc', error, res)
|
2014-02-12 10:40:42 +00:00
|
|
|
return callback(error) if error?
|
|
|
|
if res.statusCode >= 200 and res.statusCode < 300
|
|
|
|
return callback null
|
|
|
|
else if res.statusCode == 404
|
|
|
|
return callback(new Errors.NotFoundError("doc not not found: #{url}"))
|
|
|
|
else
|
|
|
|
return callback(new Error("error accessing web API: #{url} #{res.statusCode}"))
|
|
|
|
|