| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- 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),
- }
|