From 939fb3d794636709b5749b5dce56b74ba2165959 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 2 Sep 2026 07:49:27 +0530 Subject: [PATCH 1/2] fix(services): close IndexedDB connections after transactions in github.js Closes #216 Ensures that IndexedDB database connection handles opened by openDB() in cacheGet, cacheSet, and cacheClear are explicitly closed on transaction completion, error, or abort. This prevents active database handle accumulation and memory leaks during large organization queries. --- src/services/github.js | 50 +++++++++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/src/services/github.js b/src/services/github.js index a4180fa..435f218 100644 --- a/src/services/github.js +++ b/src/services/github.js @@ -16,13 +16,27 @@ export async function cacheGet(key) { try { const db = await openDB() return new Promise(res => { - const req = db.transaction(STORE, 'readonly').objectStore(STORE).get(key) + const tx = db.transaction(STORE, 'readonly') + const req = tx.objectStore(STORE).get(key) + let value = null req.onsuccess = () => { const r = req.result - if (!r || Date.now() - r.ts > TTL_MS) return res(null) - res(r.v) + if (r && Date.now() - r.ts <= TTL_MS) { + value = r.v + } + } + tx.oncomplete = () => { + db.close() + res(value) + } + tx.onerror = () => { + db.close() + res(null) + } + tx.onabort = () => { + db.close() + res(null) } - req.onerror = () => res(null) }) } catch { return null } } @@ -33,8 +47,18 @@ export async function cacheSet(key, value) { return new Promise(res => { const tx = db.transaction(STORE, 'readwrite') tx.objectStore(STORE).put({ k: key, v: value, ts: Date.now() }) - tx.oncomplete = () => res(true) - tx.onerror = () => res(false) + tx.oncomplete = () => { + db.close() + res(true) + } + tx.onerror = () => { + db.close() + res(false) + } + tx.onabort = () => { + db.close() + res(false) + } }) } catch { return false } } @@ -45,8 +69,18 @@ export async function cacheClear() { return new Promise(res => { const tx = db.transaction(STORE, 'readwrite') tx.objectStore(STORE).clear() - tx.oncomplete = () => res(true) - tx.onerror = () => res(false) + tx.oncomplete = () => { + db.close() + res(true) + } + tx.onerror = () => { + db.close() + res(false) + } + tx.onabort = () => { + db.close() + res(false) + } }) } catch { return false } } From 50f4aad17f3206a030e2c8bcdeb740e90806704a Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 2 Sep 2026 08:09:43 +0530 Subject: [PATCH 2/2] fix(settings): check cacheClear status before setting cleared state Verify that cacheClear returns true before setting the cleared success feedback state in SettingsPage. --- src/pages/SettingsPage.jsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/pages/SettingsPage.jsx b/src/pages/SettingsPage.jsx index 2f26741..16b62af 100644 --- a/src/pages/SettingsPage.jsx +++ b/src/pages/SettingsPage.jsx @@ -53,9 +53,11 @@ export default function SettingsPage() { } const handleClear = async () => { - await cacheClear() - setCleared(true) - setTimeout(() => setCleared(false), 2000) + const success = await cacheClear() + if (success) { + setCleared(true) + setTimeout(() => setCleared(false), 2000) + } } const rateColor = rateLimit