From c5bc4a12595f18dc1cff7ee455f7ca27acca4511 Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Tue, 10 Feb 2026 12:55:32 +0100 Subject: [PATCH] [clsi] tweak logging for clsi-cache (#31452) * [clsi] tweak logging for clsi-cache - Use `clsi-cache` identifier on log line - Add shard to context - Record nFiles on "too many entries for tar" error * [clsi] do not trip clsi-cache circuit breaker on ENOENT errors These can happen when an output/compile-dir is purged while we download files. GitOrigin-RevId: ffa73ef312bce5232ef72e3b81966bb6e14d2255 --- services/clsi/app/js/CLSICacheHandler.js | 34 ++++++++++++++++-------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/services/clsi/app/js/CLSICacheHandler.js b/services/clsi/app/js/CLSICacheHandler.js index 0af5ca907c..29a5eaf035 100644 --- a/services/clsi/app/js/CLSICacheHandler.js +++ b/services/clsi/app/js/CLSICacheHandler.js @@ -17,6 +17,7 @@ import Settings from '@overleaf/settings' import { MeteredStream } from '@overleaf/stream-utils' import OutputCacheManager from './OutputCacheManager.js' import ResourceWriter from './ResourceWriter.js' +import OError from '@overleaf/o-error' const { CACHE_SUBDIR } = OutputCacheManager const { isExtraneousFile } = ResourceWriter @@ -186,8 +187,8 @@ function notifyCLSICacheAboutBuild({ .catch(err => { tripCircuitBreaker(url) logger.warn( - { err, projectId, userId, buildId }, - 'enqueue for clsi cache failed' + { err, projectId, userId, buildId, shard }, + 'enqueue for clsi-cache failed' ) }) } @@ -220,8 +221,8 @@ function notifyCLSICacheAboutBuild({ }) .catch(err => { logger.warn( - { err, projectId, userId, buildId }, - 'build output.tar.gz for clsi cache failed' + { err, projectId, userId, buildId, shard }, + 'build output.tar.gz for clsi-cache failed' ) }) @@ -248,7 +249,9 @@ async function buildTarball({ projectId, userId, buildId, outputFiles }) { const files = outputFiles.filter(f => !isExtraneousFile(f.path)) if (files.length > MAX_ENTRIES_IN_OUTPUT_TAR) { Metrics.inc('clsi_cache_build_too_many_entries') - throw new Error('too many output files for output.tar.gz') + throw new OError('too many output files for output.tar.gz', { + nFiles: files.length, + }) } Metrics.count('clsi_cache_build_files', files.length) @@ -288,7 +291,7 @@ async function downloadOutputDotSynctexFromCompileCache( if (!OBJECT_ID_REGEX.test(projectId)) return false const shardCfg = getAvailableShard(projectId) if (!shardCfg) return false - const { url } = shardCfg + const { url, shard } = shardCfg const timer = new Metrics.Timer( 'clsi_cache_download', @@ -315,7 +318,7 @@ async function downloadOutputDotSynctexFromCompileCache( } tripCircuitBreaker(url) timer.done({ status: 'error' }) - throw err + throw OError.tag(err, 'download failed', { shard }) } await fs.promises.mkdir(outputDir, { recursive: true }) const dst = Path.join(outputDir, 'output.synctex.gz') @@ -330,11 +333,12 @@ async function downloadOutputDotSynctexFromCompileCache( ) await fs.promises.rename(tmp, dst) } catch (err) { + if (isENOENT(err)) return false tripCircuitBreaker(url) try { await fs.promises.unlink(tmp) } catch {} - throw err + throw OError.tag(err, 'stream failed', { shard }) } closeCircuitBreaker(url) timer.done({ status: 'success' }) @@ -352,7 +356,7 @@ async function downloadLatestCompileCache(projectId, userId, compileDir) { if (!OBJECT_ID_REGEX.test(projectId)) return false const shardCfg = getAvailableShard(projectId) if (!shardCfg) return false - const { url } = shardCfg + const { url, shard } = shardCfg const timer = new Metrics.Timer( 'clsi_cache_download', @@ -379,7 +383,7 @@ async function downloadLatestCompileCache(projectId, userId, compileDir) { } tripCircuitBreaker(url) timer.done({ status: 'error' }) - throw err + throw OError.tag(err, 'download failed', { shard }) } let n = 0 let abort = false @@ -423,8 +427,9 @@ async function downloadLatestCompileCache(projectId, userId, compileDir) { }) ) } catch (err) { + if (isENOENT(err)) return false tripCircuitBreaker(url) - throw err + throw OError.tag(err, 'stream failed', { shard }) } closeCircuitBreaker(url) Metrics.count('clsi_cache_download_entries', n) @@ -432,6 +437,13 @@ async function downloadLatestCompileCache(projectId, userId, compileDir) { return !abort } +/** + * @param {unknown} err + */ +function isENOENT(err) { + return err instanceof Error && 'code' in err && err.code === 'ENOENT' +} + export default { notifyCLSICacheAboutBuild, downloadLatestCompileCache,