mirror of
https://github.com/hydralauncher/hydra.git
synced 2026-01-15 16:33:02 -03:00
feat: improving performance on sources
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
import { registerEvent } from "../register-event";
|
||||
import { downloadSourcesSublevel } from "@main/level";
|
||||
import { downloadSourcesSublevel, repacksSublevel } from "@main/level";
|
||||
import { HydraApi } from "@main/services";
|
||||
import { importDownloadSourceToLocal } from "./helpers";
|
||||
import {
|
||||
importDownloadSourceToLocal,
|
||||
invalidateDownloadSourcesCache,
|
||||
} from "./helpers";
|
||||
|
||||
const addDownloadSource = async (
|
||||
_event: Electron.IpcMainInvokeEvent,
|
||||
@@ -12,6 +15,28 @@ const addDownloadSource = async (
|
||||
throw new Error("Failed to import download source");
|
||||
}
|
||||
|
||||
// Verify that repacks were actually written to the database (read-after-write)
|
||||
// This ensures all async operations are complete before proceeding
|
||||
let repackCount = 0;
|
||||
const repackIds: number[] = [];
|
||||
for await (const [, repack] of repacksSublevel.iterator()) {
|
||||
if (repack.downloadSourceId === result.id) {
|
||||
repackCount++;
|
||||
repackIds.push(repack.id);
|
||||
}
|
||||
}
|
||||
|
||||
// Log for debugging - helps identify if repacks are being created
|
||||
console.log(
|
||||
`✅ Download source ${result.id} (${result.name}) created with ${repackCount} repacks`
|
||||
);
|
||||
console.log(
|
||||
` Repack IDs: [${repackIds.slice(0, 5).join(", ")}${repackIds.length > 5 ? "..." : ""}]`
|
||||
);
|
||||
console.log(
|
||||
` Object IDs: [${result.objectIds.slice(0, 5).join(", ")}${result.objectIds.length > 5 ? "..." : ""}]`
|
||||
);
|
||||
|
||||
await HydraApi.post("/profile/download-sources", {
|
||||
urls: [url],
|
||||
});
|
||||
@@ -24,6 +49,7 @@ const addDownloadSource = async (
|
||||
{ needsAuth: false }
|
||||
);
|
||||
|
||||
// Update the source with fingerprint
|
||||
const updatedSource = await downloadSourcesSublevel.get(`${result.id}`);
|
||||
if (updatedSource) {
|
||||
await downloadSourcesSublevel.put(`${result.id}`, {
|
||||
@@ -33,6 +59,33 @@ const addDownloadSource = async (
|
||||
});
|
||||
}
|
||||
|
||||
// Final verification: ensure the source with fingerprint is persisted
|
||||
const finalSource = await downloadSourcesSublevel.get(`${result.id}`);
|
||||
if (!finalSource || !finalSource.fingerprint) {
|
||||
throw new Error("Failed to persist download source with fingerprint");
|
||||
}
|
||||
|
||||
// Verify repacks still exist after fingerprint update
|
||||
let finalRepackCount = 0;
|
||||
for await (const [, repack] of repacksSublevel.iterator()) {
|
||||
if (repack.downloadSourceId === result.id) {
|
||||
finalRepackCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (finalRepackCount !== repackCount) {
|
||||
console.warn(
|
||||
`⚠️ Repack count mismatch! Before: ${repackCount}, After: ${finalRepackCount}`
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
`✅ Final verification passed: ${finalRepackCount} repacks confirmed`
|
||||
);
|
||||
}
|
||||
|
||||
// Invalidate cache to ensure fresh data on next read
|
||||
invalidateDownloadSourcesCache();
|
||||
|
||||
return {
|
||||
...result,
|
||||
fingerprint,
|
||||
|
||||
@@ -282,6 +282,9 @@ export const importDownloadSourceToLocal = async (
|
||||
steamGames
|
||||
);
|
||||
|
||||
// Invalidate ID caches after creating new repacks to prevent ID collisions
|
||||
invalidateIdCaches();
|
||||
|
||||
return {
|
||||
...downloadSource,
|
||||
objectIds,
|
||||
|
||||
@@ -3,7 +3,7 @@ import axios, { AxiosError } from "axios";
|
||||
import { z } from "zod";
|
||||
import { downloadSourcesSublevel, repacksSublevel } from "@main/level";
|
||||
import { DownloadSourceStatus } from "@shared";
|
||||
import { invalidateDownloadSourcesCache } from "./helpers";
|
||||
import { invalidateDownloadSourcesCache, invalidateIdCaches } from "./helpers";
|
||||
|
||||
const downloadSourceSchema = z.object({
|
||||
name: z.string().max(255),
|
||||
@@ -111,19 +111,52 @@ const addNewDownloads = async (
|
||||
|
||||
for (const download of downloads) {
|
||||
const formattedTitle = formatRepackName(download.title);
|
||||
const [firstLetter] = formattedTitle;
|
||||
const games = steamGames[firstLetter] || [];
|
||||
let gamesInSteam: FormattedSteamGame[] = [];
|
||||
|
||||
const gamesInSteam = games.filter((game) =>
|
||||
formattedTitle.startsWith(game.formattedName)
|
||||
);
|
||||
// Only try to match if we have a valid formatted title
|
||||
if (formattedTitle && formattedTitle.length > 0) {
|
||||
const [firstLetter] = formattedTitle;
|
||||
const games = steamGames[firstLetter] || [];
|
||||
|
||||
if (gamesInSteam.length === 0) continue;
|
||||
// Try exact prefix match first
|
||||
gamesInSteam = games.filter((game) =>
|
||||
formattedTitle.startsWith(game.formattedName)
|
||||
);
|
||||
|
||||
// If no exact prefix match, try contains match (more lenient)
|
||||
if (gamesInSteam.length === 0) {
|
||||
gamesInSteam = games.filter(
|
||||
(game) =>
|
||||
formattedTitle.includes(game.formattedName) ||
|
||||
game.formattedName.includes(formattedTitle)
|
||||
);
|
||||
}
|
||||
|
||||
// If still no match, try checking all letters (not just first letter)
|
||||
// This helps with repacks that use abbreviations or alternate naming
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add matched game IDs to source tracking
|
||||
for (const game of gamesInSteam) {
|
||||
objectIdsOnSource.add(String(game.id));
|
||||
}
|
||||
|
||||
// Create the repack even if no games matched
|
||||
// This ensures all repacks from sources are imported
|
||||
const repack = {
|
||||
id: nextRepackId++,
|
||||
objectIds: gamesInSteam.map((game) => String(game.id)),
|
||||
@@ -248,8 +281,9 @@ const syncDownloadSources = async (
|
||||
}
|
||||
}
|
||||
|
||||
// Invalidate cache after all sync operations complete
|
||||
// Invalidate caches after all sync operations complete
|
||||
invalidateDownloadSourcesCache();
|
||||
invalidateIdCaches();
|
||||
|
||||
return newRepacksCount;
|
||||
} catch (err) {
|
||||
|
||||
Reference in New Issue
Block a user