diff --git a/services/web/app.mjs b/services/web/app.mjs index 1538e60149..b7c723da3d 100644 --- a/services/web/app.mjs +++ b/services/web/app.mjs @@ -75,7 +75,7 @@ try { await Promise.all([ mongodb.connectionPromise, mongoose.connectionPromise, - HistoryManager.promises.loadGlobalBlobs(), + HistoryManager.loadGlobalBlobsPromise, ]) } catch (err) { logger.fatal({ err }, 'Cannot connect to mongo. Exiting.') diff --git a/services/web/app/src/Features/History/HistoryManager.js b/services/web/app/src/Features/History/HistoryManager.js index 6e40907d1b..fe9e6e86a7 100644 --- a/services/web/app/src/Features/History/HistoryManager.js +++ b/services/web/app/src/Features/History/HistoryManager.js @@ -417,8 +417,11 @@ function _userView(user) { return { first_name: firstName, last_name: lastName, email, id: _id } } +const loadGlobalBlobsPromise = loadGlobalBlobs() + module.exports = { getBlobLocation, + loadGlobalBlobsPromise, initializeProject: callbackify(initializeProject), flushProject: callbackify(flushProject), resyncProject: callbackify(resyncProject), @@ -432,7 +435,6 @@ module.exports = { getLatestHistory: callbackify(getLatestHistory), getChanges: callbackify(getChanges), promises: { - loadGlobalBlobs, initializeProject, flushProject, resyncProject, diff --git a/services/web/test/unit/src/History/HistoryManagerTests.js b/services/web/test/unit/src/History/HistoryManagerTests.js index bfb13feaf2..6b83d15ed0 100644 --- a/services/web/test/unit/src/History/HistoryManagerTests.js +++ b/services/web/test/unit/src/History/HistoryManagerTests.js @@ -2,10 +2,36 @@ const { expect } = require('chai') const sinon = require('sinon') const SandboxedModule = require('sandboxed-module') const { ObjectId } = require('mongodb-legacy') +const { + connectionPromise, + cleanupTestDatabase, + db, +} = require('../../../../app/src/infrastructure/mongodb') const MODULE_PATH = '../../../../app/src/Features/History/HistoryManager' +const GLOBAL_BLOBS = { + e69de29bb2d1d6434b8b29ae775ad8c2e48c5391: + 'e6/9d/e29bb2d1d6434b8b29ae775ad8c2e48c5391', + '02426c2b3a484003ca42ed52b374b7907b757d12': + '02/42/6c2b3a484003ca42ed52b374b7907b757d12', +} + describe('HistoryManager', function () { + before(async function () { + await connectionPromise + }) + before(cleanupTestDatabase) + before(async function () { + await db.projectHistoryGlobalBlobs.insertMany( + Object.keys(GLOBAL_BLOBS).map(sha => ({ + _id: sha, + byteLength: 0, + stringLength: 0, + })) + ) + }) + beforeEach(function () { this.user_id = 'user-id-123' this.historyId = new ObjectId().toString() @@ -29,6 +55,10 @@ describe('HistoryManager', function () { url: this.v1HistoryUrl, user: this.v1HistoryUser, pass: this.v1HistoryPassword, + buckets: { + globalBlobs: 'globalBlobs', + projectBlobs: 'projectBlobs', + }, }, }, } @@ -60,7 +90,7 @@ describe('HistoryManager', function () { this.HistoryManager = SandboxedModule.require(MODULE_PATH, { requires: { - '../../infrastructure/mongodb': { ObjectId }, + '../../infrastructure/mongodb': { ObjectId, db }, '@overleaf/fetch-utils': this.FetchUtils, '@overleaf/settings': this.settings, '../User/UserGetter': this.UserGetter, @@ -70,6 +100,28 @@ describe('HistoryManager', function () { }) }) + describe('getBlobLocation', function () { + beforeEach(async function () { + await this.HistoryManager.loadGlobalBlobsPromise + }) + it('should return a global blob location', function () { + for (const [sha, key] of Object.entries(GLOBAL_BLOBS)) { + expect(this.HistoryManager.getBlobLocation('42', sha)).to.deep.equal({ + bucket: this.settings.apis.v1_history.buckets.globalBlobs, + key, + }) + } + }) + it('should return a project blob location', function () { + const sha = '6ddfa0578a67fe5ad6623a8665ec9aafce1eb5ca' + const key = '240/000/000/6d/dfa0578a67fe5ad6623a8665ec9aafce1eb5ca' + expect(this.HistoryManager.getBlobLocation('42', sha)).to.deep.equal({ + bucket: this.settings.apis.v1_history.buckets.projectBlobs, + key, + }) + }) + }) + describe('initializeProject', function () { beforeEach(function () { this.settings.apis.project_history.initializeHistoryForNewProjects = true