[clsi] initial implementation of compile from history (#31883)

* [clsi] initial implementation of compile from history

* [clsi] copy changes

* [saas-e2e] extend test case with nested folder

* [saas-e2e] add test case for tracked changes

* [web] fix accumulating changes from multiple chunks

* [web] optimize size check for compile request payload

* [clsi] deduplicate globalBlobs

* [clsi] add validation for request body details

* [clsi] add metrics for compile from history

* [clsi] download binary files concurrently

* [clsi] skip download of empty file blob

* [clsi] break down e2e compile time metric by compileFromHistory

GitOrigin-RevId: 0dadef93e89d8a172c35cb130a1042d9d1bec42a
This commit is contained in:
Jakob Ackermann
2026-03-03 11:20:08 +01:00
committed by Copybot
parent 5723a9589a
commit 81b7121408
28 changed files with 1135 additions and 88 deletions

View File

@@ -22,6 +22,7 @@ import StatsManager from './StatsManager.js'
import SafeReader from './SafeReader.js'
import LatexMetrics from './LatexMetrics.js'
import { callbackifyMultiResult } from '@overleaf/promise-utils'
import * as HistoryResourceWriter from './HistoryResourceWriter.js'
const { downloadLatestCompileCache, downloadOutputDotSynctexFromCompileCache } =
CLSICacheHandler
@@ -104,13 +105,24 @@ async function doCompile(request, stats, timings) {
'syncing resources to disk'
)
let resourceList
let resourceList, baseHistoryVersion
try {
// NOTE: resourceList is insecure, it should only be used to exclude files from the output list
resourceList = await ResourceWriter.promises.syncResourcesToDisk(
request,
compileDir
)
if (request.historyId) {
;({ resourceList, baseHistoryVersion } =
await HistoryResourceWriter.syncResourcesToDisk(
projectId,
userId,
request,
compileDir,
timings
))
} else {
// NOTE: resourceList is insecure, it should only be used to exclude files from the output list
resourceList = await ResourceWriter.promises.syncResourcesToDisk(
request,
compileDir
)
}
} catch (error) {
if (error instanceof Errors.FilesOutOfSyncError) {
OError.tag(error, 'files out of sync, please retry', {
@@ -326,7 +338,7 @@ async function doCompile(request, stats, timings) {
)
}
return { outputFiles, buildId }
return { outputFiles, buildId, baseHistoryVersion }
}
async function _saveOutputFiles({
@@ -837,6 +849,7 @@ function _emitMetrics(request, status, stats, timings) {
if (timings.compileE2E != null) {
ClsiMetrics.e2eCompileDurationSeconds.observe(
{
compileFromHistory: !!request.historyId,
compile: request.metricsOpts.compile,
group: request.compileGroup,
},