Просмотр исходного кода

Merge pull request #28656 from overleaf/em-restore-optimize-file-download

File restore: optimize file download from history

GitOrigin-RevId: c32afe7d2ede2372e95490f62e79266f5f6d58da
Eric Mc Sween 10 месяцев назад
Родитель
Сommit
84e4808812

+ 20 - 4
services/web/app/src/Features/History/RestoreManager.mjs

@@ -114,6 +114,7 @@ const RestoreManager = {
     if (!project?.overleaf?.history?.rangesSupportEnabled) {
       throw new OError('project does not have ranges support', { projectId })
     }
+    const historyId = project.overleaf.history.id
 
     const basename = Path.basename(pathname)
     let dirname = Path.dirname(pathname)
@@ -179,10 +180,9 @@ const RestoreManager = {
         filename: pathname,
       })
     ) {
-      const fsPath = await RestoreManager._writeFileVersionToDisk(
-        projectId,
-        version,
-        pathname
+      const fsPath = await RestoreManager._writeSnapshotFileToDisk(
+        historyId,
+        snapshotFile
       )
       const newFile = await EditorController.promises.upsertFile(
         projectId,
@@ -426,6 +426,22 @@ const RestoreManager = {
     }/project/${projectId}/version/${version}/${encodeURIComponent(pathname)}`
     return await FileWriter.promises.writeUrlToDisk(projectId, url)
   },
+
+  async _writeSnapshotFileToDisk(historyId, file) {
+    if (file.isEditable()) {
+      return await FileWriter.promises.writeContentToDisk(
+        historyId,
+        file.getContent()
+      )
+    } else {
+      const hash = file.getHash()
+      const { stream } = await HistoryManager.promises.requestBlob(
+        historyId,
+        hash
+      )
+      return await FileWriter.promises.writeStreamToDisk(historyId, stream)
+    }
+  },
 }
 
 export default { ...callbackifyAll(RestoreManager), promises: RestoreManager }

+ 11 - 4
services/web/test/unit/src/History/RestoreManager.test.mjs

@@ -16,6 +16,9 @@ describe('RestoreManager', function () {
   beforeEach(async function (ctx) {
     tk.freeze(Date.now()) // freeze the time for these tests
 
+    ctx.fsPath = '/tmp/path/on/disk'
+    ctx.blobStream = 'blob-stream'
+
     vi.doMock('../../../../app/src/Features/Errors/Errors.js', () => ({
       default: Errors,
     }))
@@ -71,6 +74,7 @@ describe('RestoreManager', function () {
             },
             timestamp: new Date().toISOString(),
           }),
+          requestBlob: sinon.stub().resolves({ stream: ctx.blobStream }),
         },
       }),
     }))
@@ -91,7 +95,12 @@ describe('RestoreManager', function () {
     }))
 
     vi.doMock('../../../../app/src/infrastructure/FileWriter', () => ({
-      default: (ctx.FileWriter = { promises: {} }),
+      default: (ctx.FileWriter = {
+        promises: {
+          writeStreamToDisk: sinon.stub().resolves(ctx.fsPath),
+          writeContentToDisk: sinon.stub().resolves(ctx.fsPath),
+        },
+      }),
     }))
 
     vi.doMock(
@@ -167,6 +176,7 @@ describe('RestoreManager', function () {
             getMetadata: sinon
               .stub()
               .returns(snapshotData?.files?.[pathname]?.metadata),
+            getHash: sinon.stub().returns((ctx.hash = 'somehash')),
           }),
           getFilePathnames: sinon
             .stub()
@@ -380,9 +390,6 @@ describe('RestoreManager', function () {
         overleaf: { history: { rangesSupportEnabled: true } },
         rootDoc_id: 'root-doc-id',
       })
-      ctx.RestoreManager.promises._writeFileVersionToDisk = sinon
-        .stub()
-        .resolves((ctx.fsPath = '/tmp/path/on/disk'))
       ctx.RestoreManager.promises._findOrCreateFolder = sinon
         .stub()
         .resolves((ctx.folder_id = 'mock-folder-id'))