55 lines
2.1 KiB
TypeScript
55 lines
2.1 KiB
TypeScript
import { Injectable } from "@nestjs/common";
|
|
import { Cron } from "@nestjs/schedule";
|
|
import { startOfYear } from "src/time-and-attendance/attachments/cas.util";
|
|
import { PrismaService } from "src/prisma/prisma.service";
|
|
|
|
@Injectable()
|
|
export class AttachmentArchivalService {
|
|
private readonly batch_size = Number(process.env.ARCHIVE_BATCH_SIZE || 1000);
|
|
private readonly cron_expression = process.env.ARCHIVE_CRON || '0 3 * * 1';
|
|
|
|
constructor(private readonly prisma: PrismaService) { }
|
|
|
|
|
|
@Cron(function (this: AttachmentArchivalService) { return this.cron_expression; } as any)
|
|
async runScheduled() {
|
|
await this.archiveCutoffToStartOfYear();
|
|
}
|
|
|
|
//archive everything before current year
|
|
async archiveCutoffToStartOfYear() {
|
|
const cutoff = startOfYear();
|
|
console.log(`Archival: cutoff=${cutoff.toISOString()} batch=${this.batch_size}`);
|
|
|
|
let moved = 0, total = 0, i = 0;
|
|
do {
|
|
moved = await this.archiveBatch(cutoff, this.batch_size);
|
|
total += moved;
|
|
i++;
|
|
if (moved > 0) console.log(`Batch #${i}: moved ${moved}`);
|
|
} while (moved === this.batch_size);
|
|
|
|
console.log(`Archival done: total moved : ${total}`);
|
|
return { moved: total };
|
|
}
|
|
|
|
//only moves table content to archive and not blobs.
|
|
private async archiveBatch(cutoff: Date, batch_size: number): Promise<number> {
|
|
const moved = await this.prisma.$executeRaw `
|
|
WITH moved AS (
|
|
DELETE FROM "attachments"
|
|
WHERE id IN (
|
|
SELECT id FROM "attachments"
|
|
WHERE created_at < ${cutoff}
|
|
ORDER BY id
|
|
LIMIT ${batch_size}
|
|
)
|
|
RETURNING id, sha256, owner_type, owner_id, original_name, status, retention_policy, created_by, created_at
|
|
)
|
|
INSERT INTO archive.attachments_archive
|
|
(id, sha256, owner_type, owner_id, original_name, status, retention_policy, created_by, created_at)
|
|
SELECT * FROM moved;`;
|
|
return Number(moved) || 0;
|
|
}
|
|
|
|
} |