feat: #420 reimplement icon picker (#421)

This commit is contained in:
Manuel
2024-05-04 23:00:15 +02:00
committed by GitHub
parent 51aaab2f23
commit 60a35e2583
37 changed files with 2974 additions and 10 deletions

View File

@@ -1,3 +1,4 @@
import { iconsUpdaterJob } from "~/jobs/icons-updater";
import { queuesJob } from "./jobs/queue";
import { createJobGroup } from "./lib/cron-job/group";
@@ -6,4 +7,5 @@ export const jobs = createJobGroup({
// This job is used to process queues.
queues: queuesJob,
iconsUpdater: iconsUpdaterJob,
});

View File

@@ -0,0 +1,90 @@
import { Stopwatch } from "@homarr/common";
import { db, eq } from "@homarr/db";
import { createId } from "@homarr/db/client";
import { iconRepositories, icons } from "@homarr/db/schema/sqlite";
import { fetchIconsAsync } from "@homarr/icons";
import { logger } from "@homarr/log";
import { EVERY_WEEK } from "~/lib/cron-job/constants";
import { createCronJob } from "~/lib/cron-job/creator";
export const iconsUpdaterJob = createCronJob(EVERY_WEEK).withCallback(
async () => {
logger.info(`Updating icon repository cache...`);
const stopWatch = new Stopwatch();
const repositoryIconGroups = await fetchIconsAsync();
const countIcons = repositoryIconGroups
.map((group) => group.icons.length)
.reduce((partialSum, arrayLength) => partialSum + arrayLength, 0);
logger.info(
`Successfully fetched ${countIcons} icons from ${repositoryIconGroups.length} repositories within ${stopWatch.getElapsedInHumanWords()}`,
);
const databaseIconGroups = await db.query.iconRepositories.findMany({
with: {
icons: true,
},
});
const skippedChecksums: string[] = [];
let countDeleted = 0;
let countInserted = 0;
logger.info(`Updating icons in database...`);
stopWatch.reset();
await db.transaction(async (transaction) => {
for (const repositoryIconGroup of repositoryIconGroups) {
if (!repositoryIconGroup.success) {
continue;
}
const repositoryInDb = databaseIconGroups.find(
(dbIconGroup) => dbIconGroup.slug === repositoryIconGroup.slug,
);
const repositoryIconGroupId: string = repositoryInDb?.id ?? createId();
if (!repositoryInDb?.id) {
await transaction.insert(iconRepositories).values({
id: repositoryIconGroupId,
slug: repositoryIconGroup.slug,
});
}
for (const icon of repositoryIconGroup.icons) {
if (
databaseIconGroups
.flatMap((group) => group.icons)
.some((dbIcon) => dbIcon.checksum == icon.checksum)
) {
skippedChecksums.push(icon.checksum);
continue;
}
await transaction.insert(icons).values({
id: createId(),
checksum: icon.checksum,
name: icon.fileNameWithExtension,
url: icon.imageUrl.href,
iconRepositoryId: repositoryIconGroupId,
});
countInserted++;
}
}
const deadIcons = databaseIconGroups
.flatMap((group) => group.icons)
.filter((icon) => !skippedChecksums.includes(icon.checksum));
for (const icon of deadIcons) {
await transaction
.delete(icons)
.where(eq(icons.checksum, icon.checksum));
countDeleted++;
}
});
logger.info(
`Updated database within ${stopWatch.getElapsedInHumanWords()} (-${countDeleted}, +${countInserted})`,
);
},
);

View File

@@ -3,3 +3,5 @@ export const EVERY_MINUTE = "* * * * *";
export const EVERY_5_MINUTES = "*/5 * * * *";
export const EVERY_10_MINUTES = "*/10 * * * *";
export const EVERY_HOUR = "0 * * * *";
export const EVERY_DAY = "0 0 * * */1";
export const EVERY_WEEK = "0 0 * * 1";