mirror of
https://github.com/overleaf/overleaf.git
synced 2024-12-29 13:52:48 +00:00
97 lines
3 KiB
JavaScript
97 lines
3 KiB
JavaScript
|
import { promisify } from 'util'
|
||
|
import request from 'requestretry' // allow retry on error https://github.com/FGRibreau/node-request-retry
|
||
|
import logger from '@overleaf/logger'
|
||
|
import Metrics from '@overleaf/metrics'
|
||
|
import OError from '@overleaf/o-error'
|
||
|
import Settings from '@overleaf/settings'
|
||
|
import * as Errors from './Errors.js'
|
||
|
import * as RedisManager from './RedisManager.js'
|
||
|
|
||
|
// Don't let HTTP calls hang for a long time
|
||
|
const DEFAULT_MAX_HTTP_REQUEST_LENGTH = 16000 // 16 seconds
|
||
|
|
||
|
export function getHistoryId(projectId, callback) {
|
||
|
Metrics.inc('history_id_cache_requests_total')
|
||
|
RedisManager.getCachedHistoryId(projectId, (err, cachedHistoryId) => {
|
||
|
if (err) return callback(err)
|
||
|
if (cachedHistoryId) {
|
||
|
Metrics.inc('history_id_cache_hits_total')
|
||
|
callback(null, cachedHistoryId, true)
|
||
|
} else {
|
||
|
_getProjectDetails(projectId, function (error, project) {
|
||
|
if (error) {
|
||
|
return callback(error)
|
||
|
}
|
||
|
const historyId =
|
||
|
project.overleaf &&
|
||
|
project.overleaf.history &&
|
||
|
project.overleaf.history.id
|
||
|
if (historyId != null) {
|
||
|
RedisManager.setCachedHistoryId(projectId, historyId, err => {
|
||
|
if (err) return callback(err)
|
||
|
callback(null, historyId, false)
|
||
|
})
|
||
|
} else {
|
||
|
callback(null, historyId, false)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
|
||
|
export function requestResync(projectId, callback) {
|
||
|
const path = `/project/${projectId}/history/resync`
|
||
|
_sendRequest(
|
||
|
{ path, timeout: 6 * 60000, maxAttempts: 1, method: 'POST' },
|
||
|
callback
|
||
|
)
|
||
|
}
|
||
|
|
||
|
function _getProjectDetails(projectId, callback) {
|
||
|
const path = `/project/${projectId}/details`
|
||
|
logger.debug({ projectId }, 'getting project details from web')
|
||
|
_sendRequest({ path, json: true }, callback)
|
||
|
}
|
||
|
|
||
|
function _sendRequest(options, callback) {
|
||
|
const url = `${Settings.apis.web.url}${options.path}`
|
||
|
request(
|
||
|
{
|
||
|
method: options.method || 'GET',
|
||
|
url,
|
||
|
json: options.json || false,
|
||
|
timeout: options.timeout || DEFAULT_MAX_HTTP_REQUEST_LENGTH,
|
||
|
maxAttempts: options.maxAttempts || 2, // for node-request-retry
|
||
|
auth: {
|
||
|
user: Settings.apis.web.user,
|
||
|
pass: Settings.apis.web.pass,
|
||
|
sendImmediately: true,
|
||
|
},
|
||
|
},
|
||
|
function (error, res, body) {
|
||
|
if (error != null) {
|
||
|
return callback(OError.tag(error))
|
||
|
}
|
||
|
if (res.statusCode === 404) {
|
||
|
logger.debug({ url }, 'got 404 from web api')
|
||
|
error = new Errors.NotFoundError('got a 404 from web api')
|
||
|
return callback(error)
|
||
|
}
|
||
|
if (res.statusCode >= 200 && res.statusCode < 300) {
|
||
|
callback(null, body)
|
||
|
} else {
|
||
|
error = new OError(
|
||
|
`web returned a non-success status code: ${res.statusCode} (attempts: ${res.attempts})`,
|
||
|
{ url, res }
|
||
|
)
|
||
|
callback(error)
|
||
|
}
|
||
|
}
|
||
|
)
|
||
|
}
|
||
|
|
||
|
export const promises = {
|
||
|
getHistoryId: promisify(getHistoryId),
|
||
|
requestResync: promisify(requestResync),
|
||
|
}
|