mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
7f48c67512
* Add `unicorn/prefer-node-protocol` * Fix `unicorn/prefer-node-protocol` ESLint errors * Run `npm run format:fix` * Add sandboxed-module sourceTransformers in mocha setups Fix `no such file or directory, open 'node:fs'` in `sandboxed-module` * Remove `node:` in the SandboxedModule requires * Fix new linting errors with `node:` GitOrigin-RevId: 68f6e31e2191fcff4cb8058dd0a6914c14f59926
109 lines
2.9 KiB
JavaScript
109 lines
2.9 KiB
JavaScript
import { callbackify } from 'node:util'
|
|
import { setTimeout } from 'node:timers/promises'
|
|
import logger from '@overleaf/logger'
|
|
import Metrics from '@overleaf/metrics'
|
|
import Settings from '@overleaf/settings'
|
|
import {
|
|
fetchNothing,
|
|
fetchJson,
|
|
RequestFailedError,
|
|
} from '@overleaf/fetch-utils'
|
|
import * as Errors from './Errors.js'
|
|
import * as RedisManager from './RedisManager.js'
|
|
|
|
let RETRY_TIMEOUT_MS = 5000
|
|
|
|
async function getHistoryId(projectId) {
|
|
Metrics.inc('history_id_cache_requests_total')
|
|
const cachedHistoryId =
|
|
await RedisManager.promises.getCachedHistoryId(projectId)
|
|
if (cachedHistoryId) {
|
|
Metrics.inc('history_id_cache_hits_total')
|
|
return cachedHistoryId
|
|
} else {
|
|
const project = await _getProjectDetails(projectId)
|
|
const historyId =
|
|
project.overleaf &&
|
|
project.overleaf.history &&
|
|
project.overleaf.history.id
|
|
if (historyId != null) {
|
|
await RedisManager.promises.setCachedHistoryId(projectId, historyId)
|
|
}
|
|
return historyId
|
|
}
|
|
}
|
|
|
|
async function requestResync(projectId, opts = {}) {
|
|
try {
|
|
const body = {}
|
|
if (opts.historyRangesMigration) {
|
|
body.historyRangesMigration = opts.historyRangesMigration
|
|
}
|
|
await fetchNothing(
|
|
`${Settings.apis.web.url}/project/${projectId}/history/resync`,
|
|
{
|
|
method: 'POST',
|
|
signal: AbortSignal.timeout(6 * 60000),
|
|
basicAuth: {
|
|
user: Settings.apis.web.user,
|
|
password: Settings.apis.web.pass,
|
|
},
|
|
json: body,
|
|
}
|
|
)
|
|
} catch (err) {
|
|
if (err instanceof RequestFailedError && err.response.status === 404) {
|
|
throw new Errors.NotFoundError('got a 404 from web api').withCause(err)
|
|
} else {
|
|
throw err
|
|
}
|
|
}
|
|
}
|
|
|
|
async function _getProjectDetails(projectId, callback) {
|
|
logger.debug({ projectId }, 'getting project details from web')
|
|
let attempts = 0
|
|
while (true) {
|
|
attempts += 1
|
|
try {
|
|
return await fetchJson(
|
|
`${Settings.apis.web.url}/project/${projectId}/details`,
|
|
{
|
|
signal: AbortSignal.timeout(16000),
|
|
basicAuth: {
|
|
user: Settings.apis.web.user,
|
|
password: Settings.apis.web.pass,
|
|
},
|
|
}
|
|
)
|
|
} catch (err) {
|
|
if (err instanceof RequestFailedError && err.response.status === 404) {
|
|
throw new Errors.NotFoundError('got a 404 from web api').withCause(err)
|
|
} else if (attempts < 2) {
|
|
// retry after 5 seconds
|
|
await setTimeout(RETRY_TIMEOUT_MS)
|
|
} else {
|
|
throw err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adjust the retry timeout in tests
|
|
*/
|
|
export async function setRetryTimeoutMs(timeoutMs) {
|
|
RETRY_TIMEOUT_MS = timeoutMs
|
|
}
|
|
|
|
// EXPORTS
|
|
|
|
const getHistoryIdCb = callbackify(getHistoryId)
|
|
const requestResyncCb = callbackify(requestResync)
|
|
|
|
export { getHistoryIdCb as getHistoryId, requestResyncCb as requestResync }
|
|
|
|
export const promises = {
|
|
getHistoryId,
|
|
requestResync,
|
|
}
|