feat: moving sources to worker

This commit is contained in:
Chubby Granny Chaser
2025-10-18 14:07:44 +01:00
parent 393c55738c
commit c2273dbf71
6 changed files with 329 additions and 84 deletions

View File

@@ -192,83 +192,30 @@ export const addNewDownloads = async (
const batch = repacksSublevel.batch();
// Get title hash mapping and perform matching in worker thread
const titleHashMapping = await getTitleHashMapping();
let hashMatchCount = 0;
let fuzzyMatchCount = 0;
let noMatchCount = 0;
for (const download of downloads) {
let objectIds: string[] = [];
let usedHashMatch = false;
const { GameMatcherWorkerManager } = await import("@main/services");
const matchResult = await GameMatcherWorkerManager.matchDownloads(
downloads,
steamGames,
titleHashMapping
);
const titleHash = hashTitle(download.title);
const steamIdsFromHash = titleHashMapping[titleHash];
if (steamIdsFromHash && steamIdsFromHash.length > 0) {
hashMatchCount++;
usedHashMatch = true;
objectIds = steamIdsFromHash.map(String);
}
if (!usedHashMatch) {
let gamesInSteam: FormattedSteamGame[] = [];
const formattedTitle = formatRepackName(download.title);
if (formattedTitle && formattedTitle.length > 0) {
const [firstLetter] = formattedTitle;
const games = steamGames[firstLetter] || [];
gamesInSteam = games.filter((game) =>
formattedTitle.startsWith(game.formattedName)
);
if (gamesInSteam.length === 0) {
gamesInSteam = games.filter(
(game) =>
formattedTitle.includes(game.formattedName) ||
game.formattedName.includes(formattedTitle)
);
}
if (gamesInSteam.length === 0) {
for (const letter of Object.keys(steamGames)) {
const letterGames = steamGames[letter] || [];
const matches = letterGames.filter(
(game) =>
formattedTitle.includes(game.formattedName) ||
game.formattedName.includes(formattedTitle)
);
if (matches.length > 0) {
gamesInSteam = matches;
break;
}
}
}
if (gamesInSteam.length > 0) {
fuzzyMatchCount++;
objectIds = gamesInSteam.map((game) => String(game.id));
} else {
noMatchCount++;
}
} else {
noMatchCount++;
}
}
for (const id of objectIds) {
// Process matched results and write to database
for (const matchedDownload of matchResult.matchedDownloads) {
for (const id of matchedDownload.objectIds) {
objectIdsOnSource.add(id);
}
const repack = {
id: nextRepackId++,
objectIds: objectIds,
title: download.title,
uris: download.uris,
fileSize: download.fileSize,
objectIds: matchedDownload.objectIds,
title: matchedDownload.title,
uris: matchedDownload.uris,
fileSize: matchedDownload.fileSize,
repacker: downloadSource.name,
uploadDate: download.uploadDate,
uploadDate: matchedDownload.uploadDate,
downloadSourceId: downloadSource.id,
createdAt: now,
updatedAt: now,
@@ -280,7 +227,7 @@ export const addNewDownloads = async (
await batch.write();
logger.info(
`Matching stats for ${downloadSource.name}: Hash=${hashMatchCount}, Fuzzy=${fuzzyMatchCount}, None=${noMatchCount}`
`Matching stats for ${downloadSource.name}: Hash=${matchResult.stats.hashMatchCount}, Fuzzy=${matchResult.stats.fuzzyMatchCount}, None=${matchResult.stats.noMatchCount}`
);
const existingSource = await downloadSourcesSublevel.get(

View File

@@ -31,20 +31,10 @@ const syncDownloadSources = async (
downloadSources.push(source);
}
const existingRepacks: Array<{
id: number;
title: string;
uris: string[];
repacker: string;
fileSize: string | null;
objectIds: string[];
uploadDate: Date | string | null;
downloadSourceId: number;
createdAt: Date;
updatedAt: Date;
}> = [];
// Use a Set for O(1) lookups instead of O(n) with array.some()
const existingRepackTitles = new Set<string>();
for await (const [, repack] of repacksSublevel.iterator()) {
existingRepacks.push(repack);
existingRepackTitles.add(repack.title);
}
// Handle sources with missing fingerprints individually, don't delete all sources
@@ -77,9 +67,9 @@ const syncDownloadSources = async (
const source = downloadSourceSchema.parse(response.data);
const steamGames = await getSteamGames();
// O(1) lookup instead of O(n) - massive performance improvement
const repacks = source.downloads.filter(
(download) =>
!existingRepacks.some((repack) => repack.title === download.title)
(download) => !existingRepackTitles.has(download.title)
);
await downloadSourcesSublevel.put(`${downloadSource.id}`, {