|
@@ -1,10 +1,11 @@
|
|
|
import OError from '@overleaf/o-error'
|
|
import OError from '@overleaf/o-error'
|
|
|
|
|
+import { fetchFromCompileDomain } from './fetchFromCompileDomain'
|
|
|
|
|
|
|
|
const PDF_JS_CHUNK_SIZE = 128 * 1024
|
|
const PDF_JS_CHUNK_SIZE = 128 * 1024
|
|
|
const MAX_SUB_REQUEST_COUNT = 4
|
|
const MAX_SUB_REQUEST_COUNT = 4
|
|
|
const MAX_SUB_REQUEST_BYTES = 4 * PDF_JS_CHUNK_SIZE
|
|
const MAX_SUB_REQUEST_BYTES = 4 * PDF_JS_CHUNK_SIZE
|
|
|
const SAMPLE_NGINX_BOUNDARY = '00000000000000000001'
|
|
const SAMPLE_NGINX_BOUNDARY = '00000000000000000001'
|
|
|
-const HEADER_OVERHEAD_PER_MULTI_PART_CHUNK = composeMultipartHeader({
|
|
|
|
|
|
|
+export const HEADER_OVERHEAD_PER_MULTI_PART_CHUNK = composeMultipartHeader({
|
|
|
boundary: SAMPLE_NGINX_BOUNDARY,
|
|
boundary: SAMPLE_NGINX_BOUNDARY,
|
|
|
// Assume an upper bound of O(9GB) for the pdf size.
|
|
// Assume an upper bound of O(9GB) for the pdf size.
|
|
|
start: 9 * 1024 * 1024 * 1024,
|
|
start: 9 * 1024 * 1024 * 1024,
|
|
@@ -73,7 +74,7 @@ function preprocessFileOnce({ file, usageScore, cachedUrls }) {
|
|
|
/**
|
|
/**
|
|
|
* @param {Array} chunks
|
|
* @param {Array} chunks
|
|
|
*/
|
|
*/
|
|
|
-function estimateSizeOfMultipartResponse(chunks) {
|
|
|
|
|
|
|
+export function estimateSizeOfMultipartResponse(chunks) {
|
|
|
/*
|
|
/*
|
|
|
--boundary
|
|
--boundary
|
|
|
HEADER
|
|
HEADER
|
|
@@ -357,7 +358,7 @@ function getResponseSize(response) {
|
|
|
* @param {Response} response
|
|
* @param {Response} response
|
|
|
* @param chunk
|
|
* @param chunk
|
|
|
*/
|
|
*/
|
|
|
-function getMultipartBoundary(response, chunk) {
|
|
|
|
|
|
|
+export function getMultipartBoundary(response, chunk) {
|
|
|
if (!Array.isArray(chunk)) return ''
|
|
if (!Array.isArray(chunk)) return ''
|
|
|
|
|
|
|
|
const raw = response.headers.get('Content-Type')
|
|
const raw = response.headers.get('Content-Type')
|
|
@@ -392,7 +393,13 @@ function composeMultipartHeader({ boundary, start, end, size }) {
|
|
|
* @param {string} boundary
|
|
* @param {string} boundary
|
|
|
* @param {Object} metrics
|
|
* @param {Object} metrics
|
|
|
*/
|
|
*/
|
|
|
-function resolveMultiPartResponses({ file, chunks, data, boundary, metrics }) {
|
|
|
|
|
|
|
+export function resolveMultiPartResponses({
|
|
|
|
|
+ file,
|
|
|
|
|
+ chunks,
|
|
|
|
|
+ data,
|
|
|
|
|
+ boundary,
|
|
|
|
|
+ metrics,
|
|
|
|
|
+}) {
|
|
|
const responses = []
|
|
const responses = []
|
|
|
let offsetStart = 0
|
|
let offsetStart = 0
|
|
|
const encoder = new TextEncoder()
|
|
const encoder = new TextEncoder()
|
|
@@ -439,7 +446,7 @@ function resolveMultiPartResponses({ file, chunks, data, boundary, metrics }) {
|
|
|
* @param {number} estimatedSize
|
|
* @param {number} estimatedSize
|
|
|
* @param {RequestInit} init
|
|
* @param {RequestInit} init
|
|
|
*/
|
|
*/
|
|
|
-function checkChunkResponse(response, estimatedSize, init) {
|
|
|
|
|
|
|
+export function checkChunkResponse(response, estimatedSize, init) {
|
|
|
if (!(response.status === 206 || response.status === 200)) {
|
|
if (!(response.status === 206 || response.status === 200)) {
|
|
|
throw new OError('non successful response status: ' + response.status, {
|
|
throw new OError('non successful response status: ' + response.status, {
|
|
|
responseHeaders: Object.fromEntries(response.headers.entries()),
|
|
responseHeaders: Object.fromEntries(response.headers.entries()),
|
|
@@ -477,7 +484,7 @@ export async function fallbackRequest({ url, start, end, abortSignal }) {
|
|
|
headers: { Range: `bytes=${start}-${end - 1}` },
|
|
headers: { Range: `bytes=${start}-${end - 1}` },
|
|
|
signal: abortSignal,
|
|
signal: abortSignal,
|
|
|
}
|
|
}
|
|
|
- const response = await fetch(url, init)
|
|
|
|
|
|
|
+ const response = await fetchFromCompileDomain(url, init)
|
|
|
checkChunkResponse(response, end - start, init)
|
|
checkChunkResponse(response, end - start, init)
|
|
|
return await response.arrayBuffer()
|
|
return await response.arrayBuffer()
|
|
|
} catch (e) {
|
|
} catch (e) {
|
|
@@ -556,7 +563,7 @@ async function fetchChunk({
|
|
|
// result all the browser cache keys (aka urls) get invalidated.
|
|
// result all the browser cache keys (aka urls) get invalidated.
|
|
|
// We memorize the previous browser cache keys in `cachedUrls`.
|
|
// We memorize the previous browser cache keys in `cachedUrls`.
|
|
|
try {
|
|
try {
|
|
|
- const response = await fetch(oldUrl, init)
|
|
|
|
|
|
|
+ const response = await fetchFromCompileDomain(oldUrl, init)
|
|
|
if (response.status === 200) {
|
|
if (response.status === 200) {
|
|
|
checkChunkResponse(response, estimatedSize, init)
|
|
checkChunkResponse(response, estimatedSize, init)
|
|
|
metrics.oldUrlHitCount += 1
|
|
metrics.oldUrlHitCount += 1
|
|
@@ -571,7 +578,7 @@ async function fetchChunk({
|
|
|
// Fallback to the latest url.
|
|
// Fallback to the latest url.
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- const response = await fetch(url, init)
|
|
|
|
|
|
|
+ const response = await fetchFromCompileDomain(url, init)
|
|
|
checkChunkResponse(response, estimatedSize, init)
|
|
checkChunkResponse(response, estimatedSize, init)
|
|
|
if (chunk.hash) cachedUrls.set(chunk.hash, url)
|
|
if (chunk.hash) cachedUrls.set(chunk.hash, url)
|
|
|
return response
|
|
return response
|