forked from Aditya8369/Pollution-Control-Hub
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcacheStore.js
More file actions
106 lines (96 loc) · 2.86 KB
/
Copy pathcacheStore.js
File metadata and controls
106 lines (96 loc) · 2.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
const DB_NAME = 'pollution-hub-cache';
const STORE_NAME = 'aqi-cache';
const DB_VERSION = 1;
let db = null;
function openDB() {
return new Promise((resolve, reject) => {
if (db) return resolve(db);
const request = indexedDB.open(DB_NAME, DB_VERSION);
request.onupgradeneeded = (event) => {
const database = event.target.result;
if (!database.objectStoreNames.contains(STORE_NAME)) {
const store = database.createObjectStore(STORE_NAME, { keyPath: 'key' });
store.createIndex('timestamp', 'timestamp', { unique: false });
}
};
request.onsuccess = (event) => {
db = event.target.result;
resolve(db);
};
request.onerror = () => reject(request.error);
});
}
const inFlight = new Map();
const memoryCache = new Map();
export const cacheStore = {
async get(key) {
if (memoryCache.has(key)) return memoryCache.get(key);
try {
const database = await openDB();
return new Promise((resolve) => {
const tx = database.transaction(STORE_NAME, 'readonly');
const request = tx.objectStore(STORE_NAME).get(key);
request.onsuccess = () => {
const result = request.result;
if (result) memoryCache.set(key, result);
resolve(result || null);
};
request.onerror = () => resolve(null);
});
} catch {
return null;
}
},
async set(key, data) {
const entry = { key, data, timestamp: Date.now() };
memoryCache.set(key, entry);
try {
const database = await openDB();
const tx = database.transaction(STORE_NAME, 'readwrite');
tx.objectStore(STORE_NAME).put(entry);
} catch (err) {
console.warn('IndexedDB write failed:', err);
}
},
async invalidate(key) {
if (key) {
memoryCache.delete(key);
try {
const database = await openDB();
const tx = database.transaction(STORE_NAME, 'readwrite');
tx.objectStore(STORE_NAME).delete(key);
} catch (err) {
console.warn('IndexedDB delete failed:', err);
}
} else {
memoryCache.clear();
try {
const database = await openDB();
const tx = database.transaction(STORE_NAME, 'readwrite');
tx.objectStore(STORE_NAME).clear();
} catch (err) {
console.warn('IndexedDB clear failed:', err);
}
}
},
async isStale(key, ttl) {
const cached = memoryCache.get(key) || await this.get(key);
if (!cached) return true;
return Date.now() - cached.timestamp >= ttl;
},
async deduplicate(key, fetcher) {
if (!key) return null;
if (inFlight.has(key)) return inFlight.get(key);
const promise = (async () => {
try {
const data = await fetcher();
await this.set(key, data);
return data;
} finally {
inFlight.delete(key);
}
})();
inFlight.set(key, promise);
return promise;
}
};