Skip to content

Commit

Permalink
Merge pull request #53 from UTDNebula/fetch-cache
Browse files Browse the repository at this point in the history
Fetch cache
  • Loading branch information
TyHil authored Feb 22, 2024
2 parents bf55549 + 4c991fb commit ce4e3c9
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 26 deletions.
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;

0 comments on commit ce4e3c9

Please sign in to comment.