diff --git a/services/history-v1/storage/lib/backupVerifier.mjs b/services/history-v1/storage/lib/backupVerifier.mjs index 503aa07cc8..ba1b1bafab 100644 --- a/services/history-v1/storage/lib/backupVerifier.mjs +++ b/services/history-v1/storage/lib/backupVerifier.mjs @@ -80,17 +80,23 @@ export async function verifyBlobs(historyId, hashes, projectCache) { }) } catch (err) { if (err instanceof NotFoundError) { - throw new BackupCorruptedError('missing blob', { path, hash }) + throw new BackupCorruptedMissingBlobError('missing blob', { + path, + hash, + }) } throw err } const backupHash = await blobHash.fromStream(blob.getByteLength(), stream) if (backupHash !== hash) { - throw new BackupCorruptedError('hash mismatch for backed up blob', { - path, - hash, - backupHash, - }) + throw new BackupCorruptedInvalidBlobError( + 'hash mismatch for backed up blob', + { + path, + hash, + backupHash, + } + ) } } } @@ -173,7 +179,7 @@ export async function verifyProject(historyId, endTimestamp) { ) } catch (err) { if (err instanceof Chunk.NotPersistedError) { - throw new BackupRPOViolationError( + throw new BackupRPOViolationChunkNotBackedUpError( 'BackupRPOviolation: chunk not backed up', chunk ) @@ -236,3 +242,6 @@ export async function healthCheck() { await verifyBlob(historyId, hash) } } +export class BackupCorruptedMissingBlobError extends BackupCorruptedError {} +export class BackupCorruptedInvalidBlobError extends BackupCorruptedError {} +export class BackupRPOViolationChunkNotBackedUpError extends OError {} diff --git a/services/history-v1/test/acceptance/js/api/backupVerifier.test.mjs b/services/history-v1/test/acceptance/js/api/backupVerifier.test.mjs index 8b6836fab5..fe3a4d1591 100644 --- a/services/history-v1/test/acceptance/js/api/backupVerifier.test.mjs +++ b/services/history-v1/test/acceptance/js/api/backupVerifier.test.mjs @@ -247,9 +247,7 @@ describe('backupVerifier', function () { }) it('should emit an error message referring to a missing chunk', async function () { const stderr = response.stderr - expect(stderr).to.include('NotFoundError: no such file') - expect(stderr).to.include("bucketName: 'overleaf-test-history-chunks'") - expect(stderr).to.include("key: '340/000/000000000000000000/000000000'") + expect(stderr).to.include('BackupRPOViolationChunkNotBackedUpError') }) }) describe('when a project blob is not backed up', function () { @@ -268,7 +266,9 @@ describe('backupVerifier', function () { }) it('includes a BackupCorruptedError in stderr', function () { - expect(response.stderr).to.include('BackupCorruptedError: missing blob') + expect(response.stderr).to.include( + 'BackupCorruptedMissingBlobError: missing blob' + ) }) }) })