Merge pull request #11442 from overleaf/jpa-hybrid-pdf-download

[web] add hybrid download of compile output

GitOrigin-RevId: b9c6dfc86e3af2f7b1728e791f074ec6d5e0badf
This commit is contained in:
Jakob Ackermann 2023-01-26 12:58:52 +00:00 committed by Copybot
parent aa9b07d323
commit 1f14e08fa1
5 changed files with 75 additions and 15 deletions

View file

@ -58,9 +58,21 @@ const getSplitTestOptions = callbackify(async function (req, res) {
? Settings.compilesUserContentDomain
: Settings.pdfDownloadDomain
const { variant: hybridDomainVariant } =
await SplitTestHandler.promises.getAssignment(
editorReq,
res,
'pdf-download-domain-hybrid'
)
const enableHybridPdfDownload = hybridDomainVariant === 'enabled'
if (!req.query.enable_pdf_caching) {
// The frontend does not want to do pdf caching.
return { pdfDownloadDomain, enablePdfCaching: false }
return {
pdfDownloadDomain,
enableHybridPdfDownload,
enablePdfCaching: false,
}
}
// Double check with the latest split test assignment.
@ -74,10 +86,19 @@ const getSplitTestOptions = callbackify(async function (req, res) {
const enablePdfCaching = variant === 'enabled'
if (!enablePdfCaching) {
// Skip the lookup of the chunk size when caching is not enabled.
return { pdfDownloadDomain, enablePdfCaching: false }
return {
pdfDownloadDomain,
enableHybridPdfDownload,
enablePdfCaching: false,
}
}
const pdfCachingMinChunkSize = await getPdfCachingMinChunkSize(editorReq, res)
return { pdfDownloadDomain, enablePdfCaching, pdfCachingMinChunkSize }
return {
pdfDownloadDomain,
enableHybridPdfDownload,
enablePdfCaching,
pdfCachingMinChunkSize,
}
})
module.exports = CompileController = {
@ -118,8 +139,12 @@ module.exports = CompileController = {
getSplitTestOptions(req, res, (err, splitTestOptions) => {
if (err) return next(err)
let { enablePdfCaching, pdfCachingMinChunkSize, pdfDownloadDomain } =
splitTestOptions
let {
enablePdfCaching,
pdfCachingMinChunkSize,
pdfDownloadDomain,
enableHybridPdfDownload,
} = splitTestOptions
options.enablePdfCaching = enablePdfCaching
if (enablePdfCaching) {
options.pdfCachingMinChunkSize = pdfCachingMinChunkSize
@ -186,6 +211,7 @@ module.exports = CompileController = {
timings,
pdfDownloadDomain,
pdfCachingMinChunkSize,
enableHybridPdfDownload,
})
}
)

View file

@ -38,12 +38,16 @@ export async function fetchFromCompileDomain(url: string, init: RequestInit) {
}
}
function withFallbackCompileDomain(url: string) {
export function swapDomain(url: string, domain: string) {
const u = new URL(url)
u.hostname = new URL(getMeta('ol-fallbackCompileDomain')).hostname
u.hostname = new URL(domain).hostname
return u.href
}
function withFallbackCompileDomain(url: string) {
return swapDomain(url, getMeta('ol-fallbackCompileDomain'))
}
function recordFallbackUsage() {
setTimeout(() => {
postJSON('/record-user-content-domain-fallback-usage').catch(() => {})

View file

@ -3,7 +3,8 @@ import HumanReadableLogs from '../../../ide/human-readable-logs/HumanReadableLog
import BibLogParser from '../../../ide/log-parser/bib-log-parser'
import { v4 as uuid } from 'uuid'
import { enablePdfCaching } from './pdf-caching-flags'
import { fetchFromCompileDomain } from './fetchFromCompileDomain'
import { fetchFromCompileDomain, swapDomain } from './fetchFromCompileDomain'
import { userContentDomainAccessCheckPassed } from '../../user-content-domain-access-check'
// Warnings that may disappear after a second LaTeX pass
const TRANSIENT_WARNING_REGEX = /^(Reference|Citation).+undefined on input line/
@ -28,7 +29,8 @@ export function handleOutputFiles(outputFiles, projectId, data) {
outputFile.pdfUrl = `${buildURL(
outputFile,
data.pdfDownloadDomain
data.pdfDownloadDomain,
data.enableHybridPdfDownload
)}?${params}`
// build the URL for downloading the PDF
@ -71,7 +73,7 @@ export const handleLogFiles = async (outputFiles, data, signal) => {
if (logFile) {
try {
const response = await fetchFromCompileDomain(
buildURL(logFile, data.pdfDownloadDomain),
buildURL(logFile, data.pdfDownloadDomain, data.enableHybridPdfDownload),
{ signal }
)
@ -102,7 +104,7 @@ export const handleLogFiles = async (outputFiles, data, signal) => {
if (blgFile) {
try {
const response = await fetchFromCompileDomain(
buildURL(blgFile, data.pdfDownloadDomain),
buildURL(blgFile, data.pdfDownloadDomain, data.enableHybridPdfDownload),
{ signal }
)
@ -159,7 +161,20 @@ export function buildLogEntryAnnotations(entries, fileTreeManager) {
return logEntryAnnotations
}
function buildURL(file, pdfDownloadDomain) {
function buildURL(file, pdfDownloadDomain, enableHybridPdfDownload) {
const userContentDomain = getMeta('ol-compilesUserContentDomain')
if (
enableHybridPdfDownload &&
userContentDomainAccessCheckPassed() &&
file.build &&
userContentDomain
) {
// This user is enrolled in the hybrid download of compile output.
// The access check passed, so try to use the new user content domain.
// Downloads from the compiles domains must include a build id.
// The build id is used implicitly for access control.
return swapDomain(`${pdfDownloadDomain}${file.url}`, userContentDomain)
}
if (file.build && pdfDownloadDomain) {
// Downloads from the compiles domain must include a build id.
// The build id is used implicitly for access control.

View file

@ -204,12 +204,24 @@ export async function checkUserContentDomainAccess() {
body: { failed, succeeded: cases.length - failed },
})
} catch (e) {}
return failed === 0
}
let accessCheckPassed = false
export function userContentDomainAccessCheckPassed() {
return accessCheckPassed
}
export function scheduleUserContentDomainAccessCheck() {
sleep(INITIAL_DELAY_MS).then(() => {
checkUserContentDomainAccess().catch(err => {
captureException(err)
})
checkUserContentDomainAccess()
.then(ok => {
accessCheckPassed = ok
})
.catch(err => {
captureException(err)
})
})
}

View file

@ -121,6 +121,7 @@ describe('CompileController', function () {
},
],
pdfDownloadDomain: 'https://compiles.overleaf.test',
enableHybridPdfDownload: false,
})
)
})
@ -163,6 +164,7 @@ describe('CompileController', function () {
},
],
pdfDownloadDomain: 'https://compiles.overleaf.test/zone/b',
enableHybridPdfDownload: false,
})
)
})
@ -204,6 +206,7 @@ describe('CompileController', function () {
JSON.stringify({
status: this.status,
outputFiles: this.outputFiles,
enableHybridPdfDownload: false,
})
)
})