diff --git a/backend/src/revisions/revisions.service.spec.ts b/backend/src/revisions/revisions.service.spec.ts index 16f9ac7e9..80afb5c88 100644 --- a/backend/src/revisions/revisions.service.spec.ts +++ b/backend/src/revisions/revisions.service.spec.ts @@ -535,10 +535,12 @@ describe('RevisionsService', () => { describe('removeOldRevisions', () => { const now = 1758653425; + let expectedDateTime: string; beforeEach(() => { jest.useFakeTimers(); jest.setSystemTime(now); noteConfig.revisionRetentionDays = 1; + expectedDateTime = dateTimeToDB(getCurrentDateTime().minus({ days: 1 })); }); afterEach(() => { jest.useRealTimers(); @@ -550,9 +552,16 @@ describe('RevisionsService', () => { }); it("doesn't update if no revisions were removed", async () => { mockDelete(tracker, TableRevision, [FieldNameRevision.createdAt], []); + mockSelect( + tracker, + [FieldNameRevision.noteId], + TableRevision, + [FieldNameRevision.createdAt], + [], + ); await service.removeOldRevisions(); - expectBindings(tracker, 'delete', [[now - 24 * 60 * 60 * 1000]]); - expectBindings(tracker, 'select', [], false, true); + expectBindings(tracker, 'delete', [[expectedDateTime]]); + expectBindings(tracker, 'select', [[expectedDateTime]]); }); it('updates notes if revisions were deleted', async () => { // The typecast is required since jest does not see all signatures of the mocked function @@ -572,6 +581,17 @@ describe('RevisionsService', () => { }, ], ); + mockSelect( + tracker, + [FieldNameRevision.noteId], + TableRevision, + [FieldNameRevision.createdAt], + [ + { + [FieldNameRevision.noteId]: mockNoteId, + }, + ], + ); mockSelect( tracker, [ @@ -606,8 +626,12 @@ describe('RevisionsService', () => { 1, ); await service.removeOldRevisions(); - expectBindings(tracker, 'delete', [[now - 24 * 60 * 60 * 1000]]); - expectBindings(tracker, 'select', [[mockNoteId, true]]); + + expectBindings(tracker, 'delete', [[expectedDateTime]]); + expectBindings(tracker, 'select', [ + [expectedDateTime], + [mockNoteId, true], + ]); expectBindings(tracker, 'update', [ [ `${mockPatch}\n${mockPrimaryAlias}\n\n${mockContent1}`, diff --git a/backend/src/revisions/revisions.service.ts b/backend/src/revisions/revisions.service.ts index 755b87bb6..09e3277fe 100644 --- a/backend/src/revisions/revisions.service.ts +++ b/backend/src/revisions/revisions.service.ts @@ -478,36 +478,37 @@ export class RevisionsService { * Deletes old revisions except the latest one if the clean-up is enabled */ async removeOldRevisions(): Promise { - const currentTime = new Date().getTime(); + const currentTime = getCurrentDateTime(); const revisionRetentionDays: number = this.noteConfig.revisionRetentionDays; if (revisionRetentionDays <= 0) { return; } - const revisionRetentionMilliSeconds = - revisionRetentionDays * 24 * 60 * 60 * 1000; - + const oldestRevisionToKeepTime = currentTime.minus({ + days: revisionRetentionDays, + }); + const oldestRevisionToKeepDBTime = dateTimeToDB(oldestRevisionToKeepTime); await this.knex.transaction(async (transaction) => { // Delete old revisions - const noteIdsWhereRevisionWereDeleted = await transaction(TableRevision) - .where( - FieldNameRevision.createdAt, - '<=', - currentTime - revisionRetentionMilliSeconds, - ) - .delete(FieldNameRevision.noteId); + const noteIdsWhereRevisionsAreDeleted = await transaction(TableRevision) + .select(FieldNameRevision.noteId) + .where(FieldNameRevision.createdAt, '<=', oldestRevisionToKeepDBTime); + + await transaction(TableRevision) + .where(FieldNameRevision.createdAt, '<=', oldestRevisionToKeepDBTime) + .delete(); this.logger.log( - `${noteIdsWhereRevisionWereDeleted.length} old revisions were removed from the DB`, + `${noteIdsWhereRevisionsAreDeleted.length} old revisions were removed from the DB`, 'removeOldRevisions', ); - if (noteIdsWhereRevisionWereDeleted.length === 0) { + if (noteIdsWhereRevisionsAreDeleted.length === 0) { return; } const uniqueNoteIds = Array.from( new Set( - noteIdsWhereRevisionWereDeleted.map( + noteIdsWhereRevisionsAreDeleted.map( (entry) => entry[FieldNameRevision.noteId], ), ),