From 5067c0b22d6bc732c9308e6b9bdc447acc5be032 Mon Sep 17 00:00:00 2001 From: Alf Eaton Date: Wed, 7 Aug 2024 08:57:11 +0100 Subject: [PATCH] Merge pull request #19712 from overleaf/ae-fetch-first-log-part Stream and truncate large log files GitOrigin-RevId: 9d9058d1cc0b3c7a56b25ff34f7a41bfe3e59772 --- .../features/pdf-preview/util/output-files.js | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/services/web/frontend/js/features/pdf-preview/util/output-files.js b/services/web/frontend/js/features/pdf-preview/util/output-files.js index ad437ece4f..9d2bd7e879 100644 --- a/services/web/frontend/js/features/pdf-preview/util/output-files.js +++ b/services/web/frontend/js/features/pdf-preview/util/output-files.js @@ -7,6 +7,8 @@ import { dirname, findEntityByPath } from '@/features/file-tree/util/path' // Warnings that may disappear after a second LaTeX pass const TRANSIENT_WARNING_REGEX = /^(Reference|Citation).+undefined on input line/ +const MAX_LOG_SIZE = 1024 * 1024 // 1MB + export function handleOutputFiles(outputFiles, projectId, data) { const outputFile = outputFiles.get('output.pdf') if (!outputFile) return null @@ -75,12 +77,31 @@ export const handleLogFiles = async (outputFiles, data, signal) => { if (logFile) { try { - const response = await fetch(buildURL(logFile, data.pdfDownloadDomain), { - signal, + const logFileAbortController = new AbortController() + + // abort fetching the log file if the main signal is aborted + signal.addEventListener('abort', () => { + logFileAbortController.abort() }) - result.log = await response.text() + const response = await fetch(buildURL(logFile, data.pdfDownloadDomain), { + signal: logFileAbortController.signal, + }) + result.log = '' + + const reader = response.body.pipeThrough(new TextDecoderStream()) + for await (const chunk of reader) { + result.log += chunk + if (result.log.length > MAX_LOG_SIZE) { + logFileAbortController.abort() + } + } + } catch (e) { + debugConsole.warn(e) // ignore failure to fetch the log file, but log a warning + } + + try { let { errors, warnings, typesetting } = HumanReadableLogs.parse( result.log, { @@ -95,7 +116,7 @@ export const handleLogFiles = async (outputFiles, data, signal) => { accumulateResults({ errors, warnings, typesetting }) } catch (e) { - debugConsole.warn(e) // ignore failure to fetch/parse the log file, but log a warning + debugConsole.warn(e) // ignore failure to parse the log file, but log a warning } }