[misc] merge pdf caching into main (#4033)

* [frontend] WIP: pdf caching using service worker -- squashed

Ref: 920fbaa00b31530f7c457a2d93bad5e553798057
Co-Authored-By: Brian Gough <brian.gough@overleaf.com>
Co-Authored-By: Eric Mc Sween <eric.mcsween@overleaf.com>

* [misc] add contentId into the URL for protecting PDF stream contents

* [misc] gracefully handle missing ranges in serviceWorker

* [misc] support PDF stream caching for anonymous users

* [misc] polish header names and add URL to error message when fetch fails

* [misc] polish event handler registration

* [misc] limit serviceWorker scope to /project/ -- trailing slash

This will block the service worker from intercepting requests on the
 project dashboard.

* [misc] add per-request feature flag for enabling PDF stream caching

* [misc] expose compile stats and timings to the frontend

* [misc] serviceWorker: support clsiServerId and compileGroup url params

* [misc] serviceWorker: polish header maps

* [misc] serviceWorker: drop TODO for p-limit -- the browser has a queue

* [misc] serviceWorker: drop verbose log message on every fetch

* [misc] cut down size of diff in backend code

* [misc] add test case for forwarding of pdf caching and metrics details

* [misc] serviceWorker: drop all the log lines

* [misc] serviceWorker: add boundary guards to the compile request regex

Co-authored-by: Brian Gough <brian.gough@overleaf.com>
Co-authored-by: Eric Mc Sween <eric.mcsween@overleaf.com>
GitOrigin-RevId: 4b291b4a4f2866cf07bccf8ec9068f33bbfdc916
This commit is contained in:
Jakob Ackermann
2021-05-18 02:07:57 +00:00
committed by Copybot
co-authored by Brian Gough Eric Mc Sween
parent 2901de7830
commit 7db7cd4a49
13 changed files with 420 additions and 19 deletions
@@ -124,12 +124,20 @@ describe('ClsiManager', function () {
path: 'output.pdf',
type: 'pdf',
build: 1234,
// gets dropped by JSON.stringify
contentId: undefined,
ranges: undefined,
size: undefined,
},
{
url: `/project/${this.project_id}/user/${this.user_id}/build/1234/output/output.log`,
path: 'output.log',
type: 'log',
build: 1234,
// gets dropped by JSON.stringify
contentId: undefined,
ranges: undefined,
size: undefined,
},
]
this.callback
@@ -138,6 +146,76 @@ describe('ClsiManager', function () {
})
})
describe('with ranges on the pdf and stats/timings details', function () {
beforeEach(function () {
this.ClsiManager._postToClsi = sinon.stub().yields(null, {
compile: {
status: 'success',
stats: { fooStat: 1 },
timings: { barTiming: 2 },
outputFiles: [
{
url: `${this.settings.apis.clsi.url}/project/${this.project_id}/user/${this.user_id}/build/1234/output/output.pdf`,
path: 'output.pdf',
type: 'pdf',
build: 1234,
contentId: '123-321',
ranges: [{ start: 1, end: 42, hash: 'foo' }],
size: 42,
},
{
url: `${this.settings.apis.clsi.url}/project/${this.project_id}/user/${this.user_id}/build/1234/output/output.log`,
path: 'output.log',
type: 'log',
build: 1234,
},
],
},
})
this.ClsiCookieManager._getServerId.yields(null, 'clsi-server-id-42')
this.ClsiManager.sendRequest(
this.project_id,
this.user_id,
{ compileGroup: 'standard' },
this.callback
)
})
it('should emit the caching details and stats/timings', function () {
const outputFiles = [
{
url: `/project/${this.project_id}/user/${this.user_id}/build/1234/output/output.pdf`,
path: 'output.pdf',
type: 'pdf',
build: 1234,
contentId: '123-321',
ranges: [{ start: 1, end: 42, hash: 'foo' }],
size: 42,
},
{
url: `/project/${this.project_id}/user/${this.user_id}/build/1234/output/output.log`,
path: 'output.log',
type: 'log',
build: 1234,
// gets dropped by JSON.stringify
contentId: undefined,
ranges: undefined,
size: undefined,
},
]
const validationError = undefined
expect(this.callback).to.have.been.calledWith(
null,
'success',
outputFiles,
'clsi-server-id-42',
validationError,
{ fooStat: 1 },
{ barTiming: 2 }
)
})
})
describe('with a failed compile', function () {
beforeEach(function () {
this.ClsiManager._postToClsi = sinon.stub().callsArgWith(4, null, {
@@ -317,12 +395,20 @@ describe('ClsiManager', function () {
path: 'output.pdf',
type: 'pdf',
build: 1234,
// gets dropped by JSON.stringify
contentId: undefined,
ranges: undefined,
size: undefined,
},
{
url: `/project/${this.submission_id}/build/1234/output/output.log`,
path: 'output.log',
type: 'log',
build: 1234,
// gets dropped by JSON.stringify
contentId: undefined,
ranges: undefined,
size: undefined,
},
]
this.callback
@@ -528,6 +614,7 @@ describe('ClsiManager', function () {
syncType: undefined, // "full"
syncState: undefined,
compileGroup: 'standard',
enablePdfCaching: false,
}, // "01234567890abcdef"
rootResourcePath: 'main.tex',
resources: [
@@ -623,6 +710,7 @@ describe('ClsiManager', function () {
syncType: 'incremental',
syncState: '01234567890abcdef',
compileGroup: 'priority',
enablePdfCaching: false,
},
rootResourcePath: 'main.tex',
resources: [
@@ -105,7 +105,10 @@ describe('CompileController', function () {
it('should do the compile without the auto compile flag', function () {
return this.CompileManager.compile
.calledWith(this.project_id, this.user_id, { isAutoCompile: false })
.calledWith(this.project_id, this.user_id, {
isAutoCompile: false,
enablePdfCaching: false,
})
.should.equal(true)
})
@@ -132,7 +135,10 @@ describe('CompileController', function () {
it('should do the compile with the auto compile flag', function () {
return this.CompileManager.compile
.calledWith(this.project_id, this.user_id, { isAutoCompile: true })
.calledWith(this.project_id, this.user_id, {
isAutoCompile: true,
enablePdfCaching: false,
})
.should.equal(true)
})
})
@@ -147,6 +153,7 @@ describe('CompileController', function () {
return this.CompileManager.compile
.calledWith(this.project_id, this.user_id, {
isAutoCompile: false,
enablePdfCaching: false,
draft: true,
})
.should.equal(true)