Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fetch cache #53

Merged
merged 2 commits into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions src/data/fetch.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import fetchWithCache, {
cacheIndexGrades,
cacheIndexProfessor,
} from '~data/fetchWithCache';

interface FetchProfessorParameters {
profFirst: string;
profLast: string;
Expand All @@ -6,7 +11,7 @@ interface FetchProfessorParameters {
export async function fetchNebulaProfessor(
params: FetchProfessorParameters,
): Promise<unknown> {
return fetch(
return fetchWithCache(
'https://trends.utdnebula.com/api/professor?profFirst=' +
params.profFirst +
'&profLast=' +
Expand All @@ -17,8 +22,9 @@ export async function fetchNebulaProfessor(
Accept: 'application/json',
},
},
cacheIndexProfessor,
2629800000,
)
.then((response) => response.json())
.then((data) => {
if (data.message !== 'success') {
//throw new Error(data.message);
Expand All @@ -34,7 +40,7 @@ export async function fetchNebulaProfessor(
export async function fetchNebulaGrades(
params: FetchProfessorParameters,
): Promise<unknown> {
return fetch(
return fetchWithCache(
'https://trends.utdnebula.com/api/grades?profFirst=' +
params.profFirst +
'&profLast=' +
Expand All @@ -45,8 +51,9 @@ export async function fetchNebulaGrades(
Accept: 'application/json',
},
},
cacheIndexGrades,
2629800000,
)
.then((response) => response.json())
.then((data) => {
if (data.message !== 'success') {
throw new Error(data.message);
Expand All @@ -59,6 +66,4 @@ export async function fetchNebulaGrades(
}

// Test function. Commented out. Uncomment to test.
// console.log(await fetchNebulaCourse({courseNumber: "4337", subjectPrefix: "CS"}));
// console.log(await fetchNebulaProfessor({firstName: "Scott", lastName: "Dollinger"}));
// console.log(await fetchNebulaSections({ courseReference: "623fedfabf28b6d88d6c7742", professorReference: "623fc346b8bc16815e8679a9" }))
// console.log(await fetchNebulaProfessor({profFirst: "Scott", profLast: "Dollinger"}));
49 changes: 30 additions & 19 deletions src/data/fetchFromRmp.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { HEADERS, PROFESSOR_QUERY, RMP_GRAPHQL_URL } from '~data/config';
import fetchWithCache, { cacheIndexRmp } from '~data/fetchWithCache';

function reportError(context, err) {
console.error('Error in ' + context + ': ' + err);
Expand Down Expand Up @@ -72,7 +73,9 @@ function fetchRetry(url: string, delay: number, tries: number, fetchOptions) {
fetchRetry(url, delay, triesLeft, fetchOptions),
);
}
return fetch(url, fetchOptions).catch(onError);
return fetchWithCache(url, fetchOptions, cacheIndexRmp, 2629800000).catch(
onError,
);
}

async function validateResponse(response, fetchOptions) {
Expand All @@ -97,19 +100,22 @@ async function validateResponse(response, fetchOptions) {

function fetchWithGraphQl(graphQlUrlProp, resolve) {
try {
fetch(RMP_GRAPHQL_URL, graphQlUrlProp).then((response) =>
validateResponse(response, graphQlUrlProp)
.then((response) => response.json())
.then((rating) => {
if (
rating != null &&
Object.hasOwn(rating, 'data') &&
Object.hasOwn(rating['data'], 'node')
) {
rating = rating['data']['node'];
}
resolve(rating);
}),
fetchWithCache(
RMP_GRAPHQL_URL,
graphQlUrlProp,
cacheIndexRmp,
2629800000,
).then((response) =>
validateResponse(response, graphQlUrlProp).then((rating) => {
if (
rating != null &&
Object.hasOwn(rating, 'data') &&
Object.hasOwn(rating['data'], 'node')
) {
rating = rating['data']['node'];
}
resolve(rating);
}),
);
} catch (err) {
reportError('fetchWithGraphQl', err);
Expand All @@ -125,19 +131,24 @@ export function requestProfessorFromRmp(
request: RmpRequest,
): Promise<RMPInterface> {
return new Promise((resolve, reject) => {
// make a list of urls for promises
// url for promises
const professorUrl = getProfessorUrl(
request.professorName,
request.schoolId,
);

// fetch professor ids from each url
fetch(professorUrl)
.then((response) => response.text())
// fetch professor id from url
fetchWithCache(
professorUrl,
{ method: 'GET' },
cacheIndexRmp,
2629800000,
true,
)
.then((text) => {
const professorId = getProfessorId(text, request.professorName);

// create fetch objects for each professor id
// create fetch object for professor id
const graphQlUrlProp = getGraphQlUrlProp(professorId);

// fetch professor info by id with graphQL
Expand Down
90 changes: 90 additions & 0 deletions src/data/fetchWithCache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { Storage } from '@plasmohq/storage';

const storage = new Storage({
area: 'local',
});

//Increment these to reset cache on next deployment
export const cacheIndexProfessor = 0;
export const cacheIndexGrades = 0;
export const cacheIndexRmp = 0;

function getCache(key: string, cacheIndex: number) {
return new Promise((resolve, reject) => {
if (process.env.NODE_ENV !== 'development') {
storage
.get(key)
.then((item) => {
if (typeof item !== 'undefined') {
const parsedItem = JSON.parse(item);
if (
!('cacheIndex' in parsedItem) ||
cacheIndex !== parsedItem.cacheIndex ||
!('expiry' in parsedItem) ||
new Date().getTime() > parsedItem.expiry ||
!('value' in parsedItem)
) {
storage.remove(key);
resolve(false);
} else {
resolve(parsedItem.value);
}
} else {
resolve(false);
}
})
.catch((error) => {
reject(error);
});
} else {
resolve(false);
}
});
}

function setCache(
key: string,
cacheIndex: number,
data: object,
expireTime: number,
) {
storage.set(
key,
JSON.stringify({
value: data,
expiry: new Date().getTime() + expireTime,
cacheIndex: cacheIndex,
}),
);
}

function fetchWithCache(
url: string,
params: unknown,
cacheIndex: number,
expireTime: number,
parseText: boolean = false,
) {
const cacheKey = url + JSON.stringify(params);
return getCache(cacheKey, cacheIndex)
.then((cache) => {
if (cache) {
return cache;
}
return fetch(url, params)
.then((response) => {
if (parseText) {
return response.text();
}
return response.json();
})
.then((data) => {
setCache(cacheKey, cacheIndex, data, expireTime);
return data;
});
})
.catch((error) => {
console.error(error);
});
}
export default fetchWithCache;
Loading