From bf8fd0dacf98d0b691f951aece4e4ebe23e68e29 Mon Sep 17 00:00:00 2001 From: Zamitto <167933696+zamitto@users.noreply.github.com> Date: Thu, 26 Jun 2025 19:37:28 -0300 Subject: [PATCH] feat: optimizations --- package.json | 2 +- python_rpc/main.py | 7 +++- src/main/events/catalogue/get-game-stats.ts | 23 ++++++++++++- src/main/events/index.ts | 1 - .../events/library/sync-game-by-object-id.ts | 32 ------------------- src/main/level/sublevels/game-stats-cache.ts | 11 +++++++ src/main/level/sublevels/index.ts | 1 + src/main/level/sublevels/keys.ts | 1 + .../achievements/get-game-achievement-data.ts | 2 +- src/main/services/download/types.ts | 4 +-- src/main/services/process-watcher.ts | 2 +- src/preload/index.ts | 2 -- .../game-details/game-details.context.tsx | 8 ----- src/renderer/src/declaration.d.ts | 1 - 14 files changed, 46 insertions(+), 51 deletions(-) delete mode 100644 src/main/events/library/sync-game-by-object-id.ts create mode 100644 src/main/level/sublevels/game-stats-cache.ts diff --git a/package.json b/package.json index f6e04071..718428dd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hydralauncher", - "version": "3.6.1", + "version": "3.6.2", "description": "Hydra", "main": "./out/main/index.js", "author": "Los Broxas", diff --git a/python_rpc/main.py b/python_rpc/main.py index 43972afa..152f8ffb 100644 --- a/python_rpc/main.py +++ b/python_rpc/main.py @@ -101,8 +101,13 @@ def process_list(): auth_error = validate_rpc_password() if auth_error: return auth_error + + iter_list = ['exe', 'pid', 'name'] + if sys.platform != 'win32': + iter_list.append('cwd') + iter_list.append('environ') - process_list = [proc.info for proc in psutil.process_iter(['exe', 'cwd', 'pid', 'name', 'environ'])] + process_list = [proc.info for proc in psutil.process_iter(iter_list)] return jsonify(process_list), 200 @app.route("/profile-image", methods=["POST"]) diff --git a/src/main/events/catalogue/get-game-stats.ts b/src/main/events/catalogue/get-game-stats.ts index 9961a0b2..559d3a7d 100644 --- a/src/main/events/catalogue/get-game-stats.ts +++ b/src/main/events/catalogue/get-game-stats.ts @@ -1,17 +1,38 @@ import type { GameShop, GameStats } from "@types"; import { registerEvent } from "../register-event"; import { HydraApi } from "@main/services"; +import { gamesStatsCacheSublevel, levelKeys } from "@main/level"; + +const LOCAL_CACHE_EXPIRATION = 1000 * 60 * 30; // 30 minutes const getGameStats = async ( _event: Electron.IpcMainInvokeEvent, objectId: string, shop: GameShop ) => { + const cachedStats = await gamesStatsCacheSublevel.get( + levelKeys.game(shop, objectId) + ); + + if ( + cachedStats && + cachedStats.updatedAt + LOCAL_CACHE_EXPIRATION > Date.now() + ) { + return cachedStats; + } + return HydraApi.get( `/games/stats`, { objectId, shop }, { needsAuth: false } - ); + ).then(async (data) => { + await gamesStatsCacheSublevel.put(levelKeys.game(shop, objectId), { + ...data, + updatedAt: Date.now(), + }); + + return data; + }); }; registerEvent("getGameStats", getGameStats); diff --git a/src/main/events/index.ts b/src/main/events/index.ts index e4e6ed2e..d640e251 100644 --- a/src/main/events/index.ts +++ b/src/main/events/index.ts @@ -20,7 +20,6 @@ import "./library/create-game-shortcut"; import "./library/close-game"; import "./library/delete-game-folder"; import "./library/get-game-by-object-id"; -import "./library/sync-game-by-object-id"; import "./library/get-library"; import "./library/extract-game-download"; import "./library/open-game"; diff --git a/src/main/events/library/sync-game-by-object-id.ts b/src/main/events/library/sync-game-by-object-id.ts deleted file mode 100644 index 4365b33c..00000000 --- a/src/main/events/library/sync-game-by-object-id.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { registerEvent } from "../register-event"; -import { gamesSublevel, levelKeys } from "@main/level"; -import { HydraApi } from "@main/services"; -import type { GameShop, UserGameDetails } from "@types"; - -const syncGameByObjectId = async ( - _event: Electron.IpcMainInvokeEvent, - shop: GameShop, - objectId: string -) => { - return HydraApi.get( - `/profile/games/${shop}/${objectId}` - ).then(async (res) => { - const { id, playTimeInSeconds, isFavorite, ...rest } = res; - - const gameKey = levelKeys.game(shop, objectId); - - const currentData = await gamesSublevel.get(gameKey); - - await gamesSublevel.put(gameKey, { - ...currentData, - ...rest, - remoteId: id, - playTimeInMilliseconds: playTimeInSeconds * 1000, - favorite: isFavorite ?? currentData?.favorite, - }); - - return res; - }); -}; - -registerEvent("syncGameByObjectId", syncGameByObjectId); diff --git a/src/main/level/sublevels/game-stats-cache.ts b/src/main/level/sublevels/game-stats-cache.ts new file mode 100644 index 00000000..05fa0cb3 --- /dev/null +++ b/src/main/level/sublevels/game-stats-cache.ts @@ -0,0 +1,11 @@ +import type { GameStats } from "@types"; + +import { db } from "../level"; +import { levelKeys } from "./keys"; + +export const gamesStatsCacheSublevel = db.sublevel< + string, + GameStats & { updatedAt: number } +>(levelKeys.gameStatsCache, { + valueEncoding: "json", +}); diff --git a/src/main/level/sublevels/index.ts b/src/main/level/sublevels/index.ts index 0bf742cb..f78f09b8 100644 --- a/src/main/level/sublevels/index.ts +++ b/src/main/level/sublevels/index.ts @@ -2,6 +2,7 @@ export * from "./downloads"; export * from "./games"; export * from "./game-shop-assets"; export * from "./game-shop-cache"; +export * from "./game-stats-cache"; export * from "./game-achievements"; export * from "./keys"; export * from "./themes"; diff --git a/src/main/level/sublevels/keys.ts b/src/main/level/sublevels/keys.ts index cab7c4f7..bba35169 100644 --- a/src/main/level/sublevels/keys.ts +++ b/src/main/level/sublevels/keys.ts @@ -7,6 +7,7 @@ export const levelKeys = { auth: "auth", themes: "themes", gameShopAssets: "gameShopAssets", + gameStatsCache: "gameStatsAssets", gameShopCache: "gameShopCache", gameShopCacheItem: (shop: GameShop, objectId: string, language: string) => `${shop}:${objectId}:${language}`, diff --git a/src/main/services/achievements/get-game-achievement-data.ts b/src/main/services/achievements/get-game-achievement-data.ts index 6b7bdeff..e2b663d8 100644 --- a/src/main/services/achievements/get-game-achievement-data.ts +++ b/src/main/services/achievements/get-game-achievement-data.ts @@ -5,7 +5,7 @@ import { logger } from "../logger"; import { db, gameAchievementsSublevel, levelKeys } from "@main/level"; import { AxiosError } from "axios"; -const LOCAL_CACHE_EXPIRATION = 1000 * 60 * 30; // 30 minutes +const LOCAL_CACHE_EXPIRATION = 1000 * 60 * 60; // 1 hour const getModifiedSinceHeader = ( cachedAchievements: GameAchievement | undefined diff --git a/src/main/services/download/types.ts b/src/main/services/download/types.ts index 7cecb103..e07c39a9 100644 --- a/src/main/services/download/types.ts +++ b/src/main/services/download/types.ts @@ -31,8 +31,8 @@ export interface ProcessPayload { exe: string | null; pid: number; name: string; - environ: Record | null; - cwd: string | null; + environ?: Record | null; + cwd?: string | null; } export interface PauseSeedingPayload { diff --git a/src/main/services/process-watcher.ts b/src/main/services/process-watcher.ts index 4d8b2a80..eb9febe8 100644 --- a/src/main/services/process-watcher.ts +++ b/src/main/services/process-watcher.ts @@ -25,7 +25,7 @@ interface GameExecutables { [key: string]: ExecutableInfo[]; } -const TICKS_TO_UPDATE_API = 80; +const TICKS_TO_UPDATE_API = 120; let currentTick = 1; const platform = process.platform; diff --git a/src/preload/index.ts b/src/preload/index.ts index 2a8297f1..ab2beae2 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -187,8 +187,6 @@ contextBridge.exposeInMainWorld("electron", { ipcRenderer.invoke("deleteGameFolder", shop, objectId), getGameByObjectId: (shop: GameShop, objectId: string) => ipcRenderer.invoke("getGameByObjectId", shop, objectId), - syncGameByObjectId: (shop: GameShop, objectId: string) => - ipcRenderer.invoke("syncGameByObjectId", shop, objectId), resetGameAchievements: (shop: GameShop, objectId: string) => ipcRenderer.invoke("resetGameAchievements", shop, objectId), extractGameDownload: (shop: GameShop, objectId: string) => diff --git a/src/renderer/src/context/game-details/game-details.context.tsx b/src/renderer/src/context/game-details/game-details.context.tsx index e1774e60..ce2923b2 100644 --- a/src/renderer/src/context/game-details/game-details.context.tsx +++ b/src/renderer/src/context/game-details/game-details.context.tsx @@ -182,14 +182,6 @@ export function GameDetailsContextProvider({ }) .catch(() => {}); } - - window.electron - .syncGameByObjectId(shop, objectId) - .then(() => { - if (abortController.signal.aborted) return; - updateGame(); - }) - .catch(() => {}); }, [ updateGame, dispatch, diff --git a/src/renderer/src/declaration.d.ts b/src/renderer/src/declaration.d.ts index 79c72a1c..7b2f9412 100644 --- a/src/renderer/src/declaration.d.ts +++ b/src/renderer/src/declaration.d.ts @@ -155,7 +155,6 @@ declare global { shop: GameShop, objectId: string ) => Promise; - syncGameByObjectId: (shop: GameShop, objectId: string) => Promise; onGamesRunning: ( cb: ( gamesRunning: Pick[]