mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-27 13:34:28 -04:00
feat(backend revision): add clean-up note revisions job (#5349)
This commit is contained in:
parent
b80552bb29
commit
4fce422bdb
7 changed files with 337 additions and 4 deletions
|
@ -3,11 +3,13 @@
|
|||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Cron, Timeout } from '@nestjs/schedule';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { createPatch } from 'diff';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import noteConfiguration, { NoteConfig } from '../config/note.config';
|
||||
import { NotInDBError } from '../errors/errors';
|
||||
import { ConsoleLoggerService } from '../logger/console-logger.service';
|
||||
import { Note } from '../notes/note.entity';
|
||||
|
@ -29,6 +31,9 @@ export class RevisionsService {
|
|||
private readonly logger: ConsoleLoggerService,
|
||||
@InjectRepository(Revision)
|
||||
private revisionRepository: Repository<Revision>,
|
||||
@InjectRepository(Note)
|
||||
private noteRepository: Repository<Note>,
|
||||
@Inject(noteConfiguration.KEY) private noteConfig: NoteConfig,
|
||||
private editService: EditService,
|
||||
) {
|
||||
this.logger.setContext(RevisionsService.name);
|
||||
|
@ -230,4 +235,80 @@ export class RevisionsService {
|
|||
await this.revisionRepository.save(revision);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete all old revisions everyday on 0:00 AM
|
||||
@Cron('0 0 * * *')
|
||||
async handleRevisionCleanup(): Promise<void> {
|
||||
return await this.removeOldRevisions();
|
||||
}
|
||||
|
||||
// Delete all old revisions 5 sec after startup
|
||||
@Timeout(5000)
|
||||
async handleRevisionCleanupTimeout(): Promise<void> {
|
||||
return await this.removeOldRevisions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete old {@link Revision}s except the latest one.
|
||||
*
|
||||
* @async
|
||||
*/
|
||||
async removeOldRevisions(): Promise<void> {
|
||||
const currentTime = new Date().getTime();
|
||||
const revisionRetentionDays: number = this.noteConfig.revisionRetentionDays;
|
||||
if (revisionRetentionDays <= 0) {
|
||||
return;
|
||||
}
|
||||
const revisionRetentionSeconds =
|
||||
revisionRetentionDays * 24 * 60 * 60 * 1000;
|
||||
|
||||
const notes: Note[] = await this.noteRepository.find();
|
||||
for (const note of notes) {
|
||||
const revisions: Revision[] = await this.revisionRepository.find({
|
||||
where: {
|
||||
note: { id: note.id },
|
||||
},
|
||||
order: {
|
||||
createdAt: 'ASC',
|
||||
},
|
||||
});
|
||||
|
||||
const oldRevisions = revisions
|
||||
.slice(0, -1) // always keep the latest revision
|
||||
.filter(
|
||||
(revision) =>
|
||||
new Date(revision.createdAt).getTime() <=
|
||||
currentTime - revisionRetentionSeconds,
|
||||
);
|
||||
const remainedRevisions = revisions.filter(
|
||||
(val) => !oldRevisions.includes(val),
|
||||
);
|
||||
|
||||
if (!oldRevisions.length) {
|
||||
continue;
|
||||
} else if (oldRevisions.length === revisions.length - 1) {
|
||||
const beUpdatedRevision = revisions.slice(-1)[0];
|
||||
beUpdatedRevision.patch = createPatch(
|
||||
note.publicId,
|
||||
'', // there is no older revision
|
||||
beUpdatedRevision.content,
|
||||
);
|
||||
await this.revisionRepository.save(beUpdatedRevision);
|
||||
} else {
|
||||
const beUpdatedRevision = remainedRevisions.slice(0)[0];
|
||||
beUpdatedRevision.patch = createPatch(
|
||||
note.publicId,
|
||||
oldRevisions.slice(-1)[0].content,
|
||||
beUpdatedRevision.content,
|
||||
);
|
||||
await this.revisionRepository.save(beUpdatedRevision);
|
||||
}
|
||||
|
||||
await this.revisionRepository.remove(oldRevisions);
|
||||
this.logger.log(
|
||||
`${oldRevisions.length} old revisions of the note '${note.id}' were removed from the DB`,
|
||||
'removeOldRevisions',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue