Skip to content

Commit 4844f6b

Browse files
committed
feat: cache issues and handle post load fetch
1 parent e6441c0 commit 4844f6b

File tree

4 files changed

+95
-5
lines changed

4 files changed

+95
-5
lines changed

src/home/fetch-github/fetch-issues-full.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
import { saveIssuesToCache } from "../getters/get-indexed-db";
12
import { GitHubIssue } from "../github-types";
3+
import { taskManager } from "../home";
4+
import { displayGitHubIssues } from "./fetch-and-display-previews";
25
export const organizationImageCache = new Map<string, Blob | null>(); // this should be declared in image related script
36

47
// Fetches the issues from `devpool-issues.json` file in the `__STORAGE__` branch of the `devpool-directory` repo
@@ -9,3 +12,40 @@ export async function fetchIssues(): Promise<GitHubIssue[]> {
912
const jsonData = await response.json();
1013
return jsonData;
1114
}
15+
16+
export async function postLoadUpdateIssues() {
17+
try {
18+
const cachedIssues = taskManager.getTasks();
19+
const fetchedIssues = await fetchIssues();
20+
21+
if(issuesAreDifferent(cachedIssues, fetchedIssues)) {
22+
console.log("Issues are different, updating cache");
23+
await saveIssuesToCache(fetchedIssues);
24+
await taskManager.syncTasks();
25+
void displayGitHubIssues();
26+
} else {
27+
console.log("Issues are the same, not updating cache");
28+
}
29+
} catch (error) {
30+
console.error("Error updating issues cache", error);
31+
}
32+
}
33+
34+
// Sort issues by ID
35+
function sortIssues(issues: GitHubIssue[]): GitHubIssue[] {
36+
return issues.slice().sort((a, b) => a.id - b.id);
37+
}
38+
39+
function issuesAreDifferent(cached: GitHubIssue[], fetched: GitHubIssue[]): boolean {
40+
cached = sortIssues(cached);
41+
fetched = sortIssues(fetched);
42+
43+
if (cached.length !== fetched.length) return true;
44+
45+
for (let i = 0; i < cached.length; i++) {
46+
if (cached[i].id !== fetched[i].id) {
47+
return true;
48+
}
49+
}
50+
return false;
51+
}

src/home/getters/get-indexed-db.ts

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
// this file contains functions to save and retrieve images from IndexedDB which is client-side in-browser storage
1+
import { GitHubIssue } from "../github-types";
2+
3+
// this file contains functions to save and retrieve issues/images from IndexedDB which is client-side in-browser storage
24
export async function saveImageToCache({
35
dbName,
46
storeName,
@@ -69,3 +71,49 @@ export function getImageFromCache({ dbName, storeName, orgName }: { dbName: stri
6971
};
7072
});
7173
}
74+
75+
async function openIssuesDB(): Promise<IDBDatabase> {
76+
return new Promise((resolve, reject) => {
77+
const request = indexedDB.open("IssuesDB", 2);
78+
79+
request.onupgradeneeded = (event) => {
80+
const db = (event.target as IDBOpenDBRequest).result;
81+
if (!db.objectStoreNames.contains("issues")) {
82+
db.createObjectStore("issues", { keyPath: "id" });
83+
}
84+
};
85+
86+
request.onsuccess = () => resolve(request.result);
87+
request.onerror = () => reject(request.error);
88+
});
89+
}
90+
91+
// Saves fetched issues into IndexedDB
92+
export async function saveIssuesToCache(issues: GitHubIssue[]): Promise<void> {
93+
const db = await openIssuesDB();
94+
const transaction = db.transaction("issues", "readwrite");
95+
const store = transaction.objectStore("issues");
96+
97+
for (const issue of issues) {
98+
store.put(issue); // Add or update issue
99+
}
100+
101+
return new Promise((resolve, reject) => {
102+
transaction.oncomplete = () => resolve();
103+
transaction.onerror = () => reject(transaction.error);
104+
});
105+
}
106+
107+
// Retrieves issues from IndexedDB
108+
export async function getIssuesFromCache(): Promise<GitHubIssue[]> {
109+
const db = await openIssuesDB();
110+
const transaction = db.transaction("issues", "readonly");
111+
const store = transaction.objectStore("issues");
112+
113+
return new Promise((resolve, reject) => {
114+
const request = store.getAll();
115+
116+
request.onsuccess = () => resolve(request.result || []);
117+
request.onerror = () => reject(request.error);
118+
});
119+
}

src/home/home.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { grid } from "../the-grid";
22
import { authentication } from "./authentication";
33
import { initiateDevRelTracking } from "./devrel-tracker";
44
import { displayGitHubIssues } from "./fetch-github/fetch-and-display-previews";
5+
import { postLoadUpdateIssues } from "./fetch-github/fetch-issues-full";
56
import { readyToolbar } from "./ready-toolbar";
67
import { registerServiceWorker } from "./register-service-worker";
78
import { renderServiceMessage } from "./render-service-message";
@@ -36,7 +37,8 @@ export const taskManager = new TaskManager(container);
3637
void (async function home() {
3738
void authentication();
3839
void readyToolbar();
39-
await taskManager.syncTasks(); // Sync tasks on load
40+
await taskManager.syncTasks(); // Sync tasks from cache on load
41+
await postLoadUpdateIssues(); // Update cache and issues if cache is outdated
4042
void displayGitHubIssues();
4143
if ("serviceWorker" in navigator) {
4244
registerServiceWorker();

src/home/task-manager.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { fetchAvatars } from "./fetch-github/fetch-avatar";
2-
import { fetchIssues } from "./fetch-github/fetch-issues-full";
32
import { getGitHubAccessToken } from "./getters/get-github-access-token";
3+
import { getIssuesFromCache } from "./getters/get-indexed-db";
44
import { setLocalStore } from "./getters/get-local-store";
55
import { GITHUB_TASKS_STORAGE_KEY, GitHubIssue } from "./github-types";
66

@@ -11,9 +11,9 @@ export class TaskManager {
1111
this._container = container;
1212
}
1313

14-
// Syncs tasks by fetching issues, writing them to storage and then fetching avatars
14+
// Syncs tasks by getting issues from cache, writing them to storage and then fetching avatars
1515
public async syncTasks() {
16-
const issues = await fetchIssues();
16+
const issues = await getIssuesFromCache();
1717

1818
this._tasks = issues;
1919
void this._writeToStorage(issues);

0 commit comments

Comments
 (0)