mirror of
https://iceshrimp.dev/limepotato/jormungandr-bite.git
synced 2024-11-25 11:27:31 -07:00
Improved media cleanup task
This commit is contained in:
parent
8404480e57
commit
079942eda4
4 changed files with 71 additions and 25 deletions
|
@ -190,6 +190,13 @@ reservedUsernames: [
|
||||||
# Proxy remote files (default: false)
|
# Proxy remote files (default: false)
|
||||||
#proxyRemoteFiles: true
|
#proxyRemoteFiles: true
|
||||||
|
|
||||||
|
# Media cleanup settings (defaults: false, 0, false, false)
|
||||||
|
#mediaCleanup:
|
||||||
|
# cron: true
|
||||||
|
# maxAgeDays: 30
|
||||||
|
# cleanAvatars: false
|
||||||
|
# cleanHeaders: false
|
||||||
|
|
||||||
#allowedPrivateNetworks: [
|
#allowedPrivateNetworks: [
|
||||||
# '127.0.0.1/32'
|
# '127.0.0.1/32'
|
||||||
#]
|
#]
|
||||||
|
|
|
@ -59,6 +59,13 @@ export type Source = {
|
||||||
ssl: boolean;
|
ssl: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mediaCleanup?: {
|
||||||
|
cron?: boolean;
|
||||||
|
maxAgeDays?: number;
|
||||||
|
keepAvatars?: boolean;
|
||||||
|
keepHeaders?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
proxy?: string;
|
proxy?: string;
|
||||||
proxySmtp?: string;
|
proxySmtp?: string;
|
||||||
proxyBypassHosts?: string[];
|
proxyBypassHosts?: string[];
|
||||||
|
|
|
@ -522,6 +522,21 @@ export default function () {
|
||||||
endedPollNotificationQueue.process(endedPollNotification);
|
endedPollNotificationQueue.process(endedPollNotification);
|
||||||
webhookDeliverQueue.process(64, processWebhookDeliver);
|
webhookDeliverQueue.process(64, processWebhookDeliver);
|
||||||
processDb(dbQueue);
|
processDb(dbQueue);
|
||||||
|
|
||||||
|
if (config.mediaCleanup?.cron) {
|
||||||
|
objectStorageQueue.add(
|
||||||
|
"cleanRemoteFiles",
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
repeat: {
|
||||||
|
cron: "0 0 * * *",
|
||||||
|
},
|
||||||
|
removeOnComplete: true,
|
||||||
|
removeOnFail: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
processObjectStorage(objectStorageQueue);
|
processObjectStorage(objectStorageQueue);
|
||||||
processBackground(backgroundQueue);
|
processBackground(backgroundQueue);
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,10 @@ import type Bull from "bull";
|
||||||
|
|
||||||
import { queueLogger } from "../../logger.js";
|
import { queueLogger } from "../../logger.js";
|
||||||
import { deleteFileSync } from "@/services/drive/delete-file.js";
|
import { deleteFileSync } from "@/services/drive/delete-file.js";
|
||||||
import { DriveFiles } from "@/models/index.js";
|
import { DriveFiles, Users } from "@/models/index.js";
|
||||||
import { MoreThan, Not, IsNull } from "typeorm";
|
import { MoreThan, Not, IsNull } from "typeorm";
|
||||||
|
import { User } from "@/models/entities/user.js";
|
||||||
|
import config from "@/config/index.js";
|
||||||
|
|
||||||
const logger = queueLogger.createSubLogger("clean-remote-files");
|
const logger = queueLogger.createSubLogger("clean-remote-files");
|
||||||
|
|
||||||
|
@ -11,43 +13,58 @@ export default async function cleanRemoteFiles(
|
||||||
job: Bull.Job<Record<string, unknown>>,
|
job: Bull.Job<Record<string, unknown>>,
|
||||||
done: any,
|
done: any,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
logger.info("Deleting cached remote files...");
|
let progress = 0;
|
||||||
|
let until = new Date();
|
||||||
|
until.setDate(until.getDate() - (config.mediaCleanup?.maxAgeDays ?? 0));
|
||||||
|
const avatars = config.mediaCleanup?.avatars ?? false;
|
||||||
|
const headers = config.mediaCleanup?.headers ?? false;
|
||||||
|
|
||||||
let deletedCount = 0;
|
until = until.toISOString().replace("T", " ").replace("Z", "");
|
||||||
let cursor: any = null;
|
|
||||||
|
let target = "files";
|
||||||
|
if (avatars)
|
||||||
|
if (headers) target += ", avatars & headers";
|
||||||
|
else target += " & avatars";
|
||||||
|
else if (headers) target += " & headers";
|
||||||
|
|
||||||
|
logger.info(`Deleting cached remote ${target} created before ${until}...`);
|
||||||
|
|
||||||
|
let query = DriveFiles.createQueryBuilder("file")
|
||||||
|
.where(`file.isLink = FALSE`)
|
||||||
|
.andWhere(`file.userHost IS NOT NULL`)
|
||||||
|
.andWhere("file.createdAt < :until", { until });
|
||||||
|
|
||||||
|
if (!avatars || !headers) {
|
||||||
|
query = query.andWhere((qb) => {
|
||||||
|
let sq = qb.subQuery().from(User, "user");
|
||||||
|
|
||||||
|
if (!avatars) sq = sq.where("file.id = user.avatarId");
|
||||||
|
if (!headers) sq = sq.orWhere("file.id = user.bannerId");
|
||||||
|
|
||||||
|
return `NOT EXISTS ${sq.getQuery()}`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
query = query.take(8);
|
||||||
|
|
||||||
|
const total = await query.getCount();
|
||||||
|
logger.info(`Deleting ${total} files, please wait...`);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
const files = await DriveFiles.find({
|
const files = await query.getMany();
|
||||||
where: {
|
|
||||||
userHost: Not(IsNull()),
|
|
||||||
isLink: false,
|
|
||||||
...(cursor ? { id: MoreThan(cursor) } : {}),
|
|
||||||
},
|
|
||||||
take: 8,
|
|
||||||
order: {
|
|
||||||
id: 1,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (files.length === 0) {
|
if (files.length === 0) {
|
||||||
job.progress(100);
|
job.progress(100);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor = files[files.length - 1].id;
|
|
||||||
|
|
||||||
await Promise.all(files.map((file) => deleteFileSync(file, true)));
|
await Promise.all(files.map((file) => deleteFileSync(file, true)));
|
||||||
|
|
||||||
deletedCount += 8;
|
progress += files.length;
|
||||||
|
|
||||||
const total = await DriveFiles.countBy({
|
job.progress((progress / total) * 100);
|
||||||
userHost: Not(IsNull()),
|
|
||||||
isLink: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
job.progress(deletedCount / total);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.succ("All cahced remote files has been deleted.");
|
logger.succ(`Remote media cleanup job completed successfully.`);
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue