From 104ae341b1cdd18b3cc84e12ee8688ef7483c2d5 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Wed, 4 Dec 2024 19:00:24 +0000 Subject: [PATCH] Merge pull request #22327 from overleaf/bg-fix-copy-blob fix bug that prevents copying blobs between different backends in history-v1 GitOrigin-RevId: 41140ad42d0d7c1beda83e588649127c22603dec --- services/history-v1/api/swagger/projects.js | 2 +- .../storage/lib/blob_store/index.js | 3 +- .../acceptance/js/storage/blob_store.test.js | 39 ++++++++++++++++++- 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/services/history-v1/api/swagger/projects.js b/services/history-v1/api/swagger/projects.js index 07b124e130..39026022d0 100644 --- a/services/history-v1/api/swagger/projects.js +++ b/services/history-v1/api/swagger/projects.js @@ -206,7 +206,7 @@ exports.paths = { name: 'copyFrom', in: 'query', description: 'source project id', - required: false, + required: true, type: 'string', }, ], diff --git a/services/history-v1/storage/lib/blob_store/index.js b/services/history-v1/storage/lib/blob_store/index.js index 64bb9d776c..c770080f7f 100644 --- a/services/history-v1/storage/lib/blob_store/index.js +++ b/services/history-v1/storage/lib/blob_store/index.js @@ -405,10 +405,11 @@ class BlobStore { const sourceProjectId = this.projectId const { bucket, key: sourceKey } = getBlobLocation(sourceProjectId, hash) const destKey = makeProjectKey(targetProjectId, hash) + const targetBackend = getBackend(targetProjectId) logger.debug({ sourceProjectId, targetProjectId, hash }, 'copyBlob started') try { await persistor.copyObject(bucket, sourceKey, destKey) - await this.backend.insertBlob(targetProjectId, sourceBlob) + await targetBackend.insertBlob(targetProjectId, sourceBlob) } finally { logger.debug( { sourceProjectId, targetProjectId, hash }, diff --git a/services/history-v1/test/acceptance/js/storage/blob_store.test.js b/services/history-v1/test/acceptance/js/storage/blob_store.test.js index e13530d1bf..531b42e400 100644 --- a/services/history-v1/test/acceptance/js/storage/blob_store.test.js +++ b/services/history-v1/test/acceptance/js/storage/blob_store.test.js @@ -480,7 +480,7 @@ describe('BlobStore', function () { }) describe('copyBlob method', function () { - it('copies a binary blob to another project', async function () { + it('copies a binary blob to another project in the same backend', async function () { const testFile = 'graph.png' const originalHash = testFiles.GRAPH_PNG_HASH const insertedBlob = await blobStore.putFile(testFiles.path(testFile)) @@ -493,7 +493,7 @@ describe('BlobStore', function () { expect(copiedBlob.getStringLength()).to.be.null }) - it('copies a text blob to another project', async function () { + it('copies a text blob to another project in the same backend', async function () { const insertedBlob = await blobStore.putString(helloWorldString) await blobStore.copyBlob(insertedBlob, scenario.projectId2) const copiedBlob = await blobStore2.getBlob(helloWorldHash) @@ -502,6 +502,41 @@ describe('BlobStore', function () { expect(content).to.equal(helloWorldString) }) }) + + describe('copyBlob method with different backends', function () { + const otherScenario = scenarios.find( + s => s.backend !== scenario.backend + ) + const otherBlobStore = new BlobStore(otherScenario.projectId2) + + beforeEach(async function () { + await otherBlobStore.initialize() + }) + + it('copies a binary blob to another project in a different backend', async function () { + const testFile = 'graph.png' + const originalHash = testFiles.GRAPH_PNG_HASH + const insertedBlob = await blobStore.putFile(testFiles.path(testFile)) + await blobStore.copyBlob(insertedBlob, otherScenario.projectId2) + const copiedBlob = await otherBlobStore.getBlob(originalHash) + expect(copiedBlob).to.exist + expect(copiedBlob.getHash()).to.equal(originalHash) + expect(copiedBlob.getByteLength()).to.equal( + insertedBlob.getByteLength() + ) + expect(copiedBlob.getStringLength()).to.be.null + }) + + it('copies a text blob to another project in a different backend', async function () { + const insertedBlob = await blobStore.putString(helloWorldString) + await blobStore.copyBlob(insertedBlob, otherScenario.projectId2) + const copiedBlob = await otherBlobStore.getBlob(helloWorldHash) + expect(copiedBlob).to.exist + expect(copiedBlob.getHash()).to.equal(helloWorldHash) + const content = await otherBlobStore.getString(helloWorldHash) + expect(content).to.equal(helloWorldString) + }) + }) }) }