Ver Fonte

Merge pull request #4153 from overleaf/bg-limit-worker-pdf-requests

limit pdf requests from service worker

GitOrigin-RevId: adb83b03325324a92567a2f7983d5cd6c3ea901a
Brian Gough há 5 anos atrás
pai
commit
d61d714da8
1 ficheiros alterados com 29 adições e 2 exclusões
  1. 29 2
      services/web/frontend/js/serviceWorker.js

+ 29 - 2
services/web/frontend/js/serviceWorker.js

@@ -1,7 +1,8 @@
 import { v4 as uuid } from 'uuid'
 import { v4 as uuid } from 'uuid'
 const COMPILE_REQUEST_MATCHER = /^\/project\/[0-9a-f]{24}\/compile$/
 const COMPILE_REQUEST_MATCHER = /^\/project\/[0-9a-f]{24}\/compile$/
 const PDF_JS_CHUNK_SIZE = 128 * 1024
 const PDF_JS_CHUNK_SIZE = 128 * 1024
-
+const MAX_SUBREQUEST_COUNT = 8
+const MAX_SUBREQUEST_BYTES = 4 * PDF_JS_CHUNK_SIZE
 const PDF_FILES = new Map()
 const PDF_FILES = new Map()
 
 
 const METRICS = {
 const METRICS = {
@@ -44,6 +45,15 @@ function trackChunkVerify({ sizeDiffers, mismatch, success }) {
   }
   }
 }
 }
 
 
+/**
+ * @param {Array} chunks
+ */
+function countBytes(chunks) {
+  return chunks.reduce((totalBytes, chunk) => {
+    return totalBytes + (chunk.end - chunk.start)
+  }, 0)
+}
+
 /**
 /**
  * @param {FetchEvent} event
  * @param {FetchEvent} event
  */
  */
@@ -140,9 +150,26 @@ function processPdfRequest(
     .map(i => parseInt(i, 10))
     .map(i => parseInt(i, 10))
   const end = last + 1
   const end = last + 1
 
 
+  // Check that handling the range request won't trigger excessive subrequests,
+  // (to avoid unwanted latency compared to the original request).
   const chunks = getMatchingChunks(file.ranges, start, end)
   const chunks = getMatchingChunks(file.ranges, start, end)
-
   const dynamicChunks = getInterleavingDynamicChunks(chunks, start, end)
   const dynamicChunks = getInterleavingDynamicChunks(chunks, start, end)
+  const chunksSize = countBytes(chunks)
+
+  if (chunks.length + dynamicChunks.length > MAX_SUBREQUEST_COUNT) {
+    // fall back to the original range request when splitting the range creates
+    // too many subrequests.
+    return
+  }
+  if (
+    chunksSize > MAX_SUBREQUEST_BYTES &&
+    !(dynamicChunks.length === 0 && chunks.length === 1)
+  ) {
+    // fall back to the original range request when a very large amount of
+    // object data would be requested, unless it is the only object in the
+    // request.
+    return
+  }
 
 
   // URL prefix is /project/:id/user/:id/build/... or /project/:id/build/...
   // URL prefix is /project/:id/user/:id/build/... or /project/:id/build/...
   //  for authenticated and unauthenticated users respectively.
   //  for authenticated and unauthenticated users respectively.