Merge pull request #25958 from overleaf/bg-history-redis-check-persisted-version-on-update

prevent setPersistedVersion from setting an out of bounds version

GitOrigin-RevId: 9561b7b96399bed901db5c2ac20a0cdbf4c67395
This commit is contained in:
Brian Gough
2025-06-03 14:34:10 +01:00
committed by Copybot
parent edacb9ec0b
commit 54c0eb7fdc
2 changed files with 36 additions and 3 deletions

View File

@@ -501,6 +501,11 @@ rclient.defineCommand('set_persisted_version', {
return 'too_low'
end
-- Refuse to set a persisted version that is higher than the head version
if newPersistedVersion > headVersion then
return 'too_high'
end
-- Set the persisted version
redis.call('SET', persistedVersionKey, newPersistedVersion)
@@ -541,6 +546,13 @@ async function setPersistedVersion(projectId, persistedVersion) {
status,
})
if (status === 'too_high') {
throw new VersionOutOfBoundsError(
'Persisted version cannot be higher than head version',
{ projectId, persistedVersion }
)
}
return status
} catch (err) {
metrics.inc('chunk_store.redis.set_persisted_version', 1, {

View File

@@ -714,10 +714,20 @@ describe('chunk buffer Redis backend', function () {
})
it('should set the persisted version', async function () {
await redisBackend.setPersistedVersion(projectId, 3)
const status = await redisBackend.setPersistedVersion(projectId, 3)
expect(status).to.equal('ok')
const state = await redisBackend.getState(projectId)
expect(state.persistedVersion).to.equal(3)
})
it('should refuse to set a persisted version greater than the head version', async function () {
await expect(
redisBackend.setPersistedVersion(projectId, 10)
).to.be.rejectedWith(VersionOutOfBoundsError)
// Ensure persisted version remains unchanged
const state = await redisBackend.getState(projectId)
expect(state.persistedVersion).to.be.null
})
})
describe('when the persisted version is set', function () {
@@ -730,13 +740,24 @@ describe('chunk buffer Redis backend', function () {
})
it('should set the persisted version', async function () {
await redisBackend.setPersistedVersion(projectId, 5)
const status = await redisBackend.setPersistedVersion(projectId, 5)
expect(status).to.equal('ok')
const state = await redisBackend.getState(projectId)
expect(state.persistedVersion).to.equal(5)
})
it('should not decrease the persisted version', async function () {
await redisBackend.setPersistedVersion(projectId, 2)
const status = await redisBackend.setPersistedVersion(projectId, 2)
expect(status).to.equal('too_low')
const state = await redisBackend.getState(projectId)
expect(state.persistedVersion).to.equal(3)
})
it('should refuse to set a persisted version greater than the head version', async function () {
await expect(
redisBackend.setPersistedVersion(projectId, 10)
).to.be.rejectedWith(VersionOutOfBoundsError)
// Ensure persisted version remains unchanged
const state = await redisBackend.getState(projectId)
expect(state.persistedVersion).to.equal(3)
})