Skip to content

Commit d5d0d4d

Browse files
authored
Merge pull request #77 from oslabs-beta/main
Obsidian Version 8.0
2 parents 0e4c2ca + 4d8c9ed commit d5d0d4d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1362
-3472
lines changed

.travis.yml

-10
This file was deleted.

ObsidianWrapper/ObsidianWrapper.jsx

+120-73
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,61 @@
11
import * as React from "https://esm.sh/react@18";
22
import LFUCache from '../src/Browser/lfuBrowserCache.js';
33
import LRUCache from '../src/Browser/lruBrowserCache.js';
4+
import WTinyLFUCache from "../src/Browser/wTinyLFUBrowserCache.js";
45
import { insertTypenames } from '../src/Browser/insertTypenames.js';
6+
import { sha256 } from 'https://denopkg.com/chiefbiiko/sha256@v1.0.0/mod.ts';
57

68
const cacheContext = React.createContext();
79

810
function ObsidianWrapper(props) {
9-
const { algo, capacity } = props
10-
const [cache, setCache] = React.useState(new LFUCache(Number(capacity || 2000)));
11-
if(algo === 'LRU') setCache(new LRUCache(Number(capacity || 2000))); // You have to put your Google Chrome Obsidian developer tool extension id to connect Obsidian Wrapper with dev tool
12-
const chromeExtensionId = 'apcpdmmbhhephobnmnllbklplpaoiemo';
13-
// initialice cache in local storage
14-
//window.localStorage.setItem('cache', JSON.stringify(cache));
11+
// props to be inputted by user when using the Obsdian Wrapper
12+
const { algo, capacity, searchTerms, useCache, persistQueries } = props;
13+
// if useCache hasn't been set, default caching to true
14+
let caching = true;
15+
// if it has been set to false, turn client-side caching off
16+
if (useCache === false) caching = false;
17+
18+
// algo defaults to LFU, capacity defaults to 2000
19+
const setAlgoCap = (algo, capacity) => {
20+
let cache;
21+
if(caching && algo === 'LRU'){
22+
cache = new LRUCache(Number(capacity || 2000))
23+
} else if (caching && algo === 'W-TinyLFU'){
24+
cache = new WTinyLFUCache(Number(capacity || 2000))
25+
} else if (caching) {
26+
cache = new LFUCache(Number(capacity || 2000))
27+
}
28+
return cache;
29+
}
30+
31+
// once cache is initialized, cannot setCache
32+
// state for cache is initialized based on developer settings in wrapper
33+
// to successfully change between algo types for testing, kill the server, change the algo type in wrapper, then restart server
34+
const [cache, setCache] = React.useState(setAlgoCap(algo, capacity));
35+
36+
// FOR DEVTOOL - listening for message from content.js to be able to send algo type and capacity to devtool
37+
window.addEventListener('message', msg => {
38+
if(msg.data.type === 'algocap'){
39+
window.postMessage({
40+
algo: algo ? algo : 'LFU',
41+
capacity: capacity ? capacity : 2000
42+
})
43+
}
44+
});
1545

1646
async function query(query, options = {}) {
17-
// dev tool messages
47+
// FOR DEVTOOL - startTime is used to calculate the performance of the cache
48+
// startDate is to find out when query was made, this data is passed to devtools
1849
const startTime = Date.now();
19-
/*
20-
chrome.runtime.sendMessage(chromeExtensionId, { query: query });
21-
chrome.runtime.sendMessage(chromeExtensionId, {
22-
cache: window.localStorage.getItem('cache'),
23-
});
24-
*/
50+
const startDate = new Date(Date.now());
2551

2652
// set the options object default properties if not provided
2753
const {
2854
endpoint = '/graphql',
29-
cacheRead = true,
30-
cacheWrite = true,
55+
cacheRead = !caching ? false : true,
56+
cacheWrite = !caching ? false : true,
3157
pollInterval = null,
32-
wholeQuery = true,
58+
wholeQuery = false, //Note: logic for true is currently nonfunctional
3359
} = options;
3460

3561
// when pollInterval is not null the query will be sent to the server every inputted number of milliseconds
@@ -45,70 +71,101 @@ function ObsidianWrapper(props) {
4571
return interval;
4672
}
4773

48-
// when cacheRead set to true
49-
if (cacheRead) {
74+
// when cacheRead set to true & we are utilizing client side caching
75+
if (cacheRead && caching) {
5076
let resObj;
5177
// when the developer decides to only utilize whole query for cache
52-
if (!wholeQuery) resObj = await cache.readWholeQuery(query);
78+
if (wholeQuery) resObj = await cache.readWholeQuery(query);
79+
// attempt to read from the cache
5380
else resObj = await cache.read(query);
5481
// check if query is stored in cache
5582
if (resObj) {
5683
// returning cached response as a promise
5784
const cacheHitResponseTime = Date.now() - startTime;
5885

59-
// Allow for access of the response time
60-
// const cacheCopy = {...cache};
61-
// cacheCopy.callTime = cacheHitResponseTime;
62-
// setCache(cacheCopy);
63-
resObj['time'] = cacheHitResponseTime
86+
// FOR DEVTOOL - sends message to content.js with query metrics when query is a hit
87+
window.postMessage({
88+
type: 'query',
89+
time: cacheHitResponseTime,
90+
date: startDate.toDateString().slice(0, 24),
91+
query: query,
92+
hit: true
93+
});
6494

65-
console.log(
66-
"From cacheRead: Here's the response time on the front end: ",
67-
cacheHitResponseTime
68-
);
69-
/*chrome.runtime.sendMessage(chromeExtensionId, {
70-
cacheHitResponseTime: cacheHitResponseTime,
71-
});*/
7295
return new Promise((resolve, reject) => resolve(resObj));
7396
}
7497
// execute graphql fetch request if cache miss
7598
return new Promise((resolve, reject) => resolve(hunt(query)));
76-
// when cacheRead set to false
7799
}
78-
if (!cacheRead) {
100+
// when cacheRead set to false & not using client-side cache
101+
if (!cacheRead || !caching) {
79102
return new Promise((resolve, reject) => resolve(hunt(query)));
80103
}
81104

82-
// when cache miss or on intervals
105+
// function to be called on cache miss or on intervals or not looking in the cache
83106
async function hunt(query) {
84-
if (wholeQuery) query = insertTypenames(query);
107+
if (!wholeQuery) query = insertTypenames(query);
85108
try {
86-
// send fetch request with query
87-
const resJSON = await fetch(endpoint, {
88-
method: 'POST',
89-
headers: {
90-
'Content-Type': 'application/json',
91-
Accept: 'application/json',
92-
},
93-
body: JSON.stringify({ query }),
94-
});
109+
let resJSON;
110+
// IF WE ARE USING PERSIST QUERIES
111+
if (persistQueries) {
112+
// SEND THE HASH
113+
const hash = sha256(query, 'utf8', 'hex');
114+
resJSON = await fetch(endpoint, {
115+
method: 'POST',
116+
headers: {
117+
'Content-Type': 'application/json',
118+
Accept: 'application/json',
119+
},
120+
body: JSON.stringify({ hash }),
121+
});
122+
123+
// IF HASH WAS NOT FOUND IN HASH TABLE
124+
if (resJSON.status === 204) {
125+
// SEND NEW REQUEST WITH HASH AND QUERY
126+
resJSON = await fetch(endpoint, {
127+
method: 'POST',
128+
headers: {
129+
'Content-Type': 'application/json',
130+
Accept: 'application/json',
131+
},
132+
body: JSON.stringify({ hash, query }),
133+
});
134+
135+
}
136+
137+
// IF WE ARE NOT USING PERSIST QUERIES
138+
} else {
139+
// JUST SEND THE QUERY ONLY
140+
resJSON = await fetch(endpoint, {
141+
method: 'POST',
142+
headers: {
143+
'Content-Type': 'application/json',
144+
Accept: 'application/json',
145+
},
146+
body: JSON.stringify({ query }),
147+
});
148+
}
149+
95150
const resObj = await resJSON.json();
96151
const deepResObj = { ...resObj };
97152
// update result in cache if cacheWrite is set to true
98-
if (cacheWrite && resObj.data[Object.keys(resObj.data)[0]] !== null) {
99-
if (!wholeQuery) cache.writeWholeQuery(query, deepResObj);
153+
if (cacheWrite && caching && resObj.data[Object.keys(resObj.data)[0]] !== null) {
154+
if (wholeQuery) cache.writeWholeQuery(query, deepResObj);
100155
else if(resObj.data[Object.keys(resObj.data)[0]].length > cache.capacity) console.log('Please increase cache capacity');
101-
else cache.write(query, deepResObj);
156+
else cache.write(query, deepResObj, searchTerms);
102157
}
103158
const cacheMissResponseTime = Date.now() - startTime;
104-
/*chrome.runtime.sendMessage(chromeExtensionId, {
105-
cacheMissResponseTime: cacheMissResponseTime,
106-
});*/
107-
resObj['time'] = cacheMissResponseTime
108-
console.log(
109-
"After the hunt: Here's the response time on the front end: ",
110-
cacheMissResponseTime
111-
);
159+
160+
// FOR DEVTOOL - sends message to content.js when query is a miss
161+
window.postMessage({
162+
type: 'query',
163+
time: cacheMissResponseTime,
164+
date: startDate.toDateString().slice(0, 24),
165+
query: query,
166+
hit: false
167+
});
168+
112169
return resObj;
113170
} catch (e) {
114171
console.log(e);
@@ -121,20 +178,19 @@ function ObsidianWrapper(props) {
121178
cache.cacheClear();
122179
}
123180

181+
// NOTE - FOR DEVTOOL - no messages are currently being passed for mutations
182+
// so some logic in content.js and background.js may be missing to handle mutations
183+
124184
// breaking out writethrough logic vs. non-writethrough logic
125185
async function mutate(mutation, options = {}) {
126-
// dev tool messages
127-
// chrome.runtime.sendMessage(chromeExtensionId, {
128-
// mutation: mutation,
129-
// });
130186
const startTime = Date.now();
131187
mutation = insertTypenames(mutation);
132188
const {
133189
endpoint = '/graphql',
134-
cacheWrite = true,
190+
cacheWrite = !caching ? false : true,
135191
toDelete = false,
136192
update = null,
137-
writeThrough = true, // not true
193+
writeThrough = true, // unsure if boolean is symantically backwards or not
138194
} = options;
139195
try {
140196
if (!writeThrough) {
@@ -147,9 +203,6 @@ function ObsidianWrapper(props) {
147203
endpoint
148204
);
149205
const deleteMutationResponseTime = Date.now() - startTime;
150-
chrome.runtime.sendMessage(chromeExtensionId, {
151-
deleteMutationResponseTime: deleteMutationResponseTime,
152-
});
153206
return responseObj;
154207
} else {
155208
// for add mutation
@@ -168,15 +221,9 @@ function ObsidianWrapper(props) {
168221
// GQL call to make changes and synchronize database
169222
console.log('WriteThrough - false ', responseObj);
170223
const addOrUpdateMutationResponseTime = Date.now() - startTime;
171-
chrome.runtime.sendMessage(chromeExtensionId, {
172-
addOrUpdateMutationResponseTime: addOrUpdateMutationResponseTime,
173-
});
174224
return responseObj;
175225
}
176226
} else {
177-
// copy-paste mutate logic from 4.
178-
179-
// use cache.write instead of cache.writeThrough
180227
const responseObj = await fetch(endpoint, {
181228
method: 'POST',
182229
headers: {
@@ -185,18 +232,18 @@ function ObsidianWrapper(props) {
185232
},
186233
body: JSON.stringify({ query: mutation }),
187234
}).then((resp) => resp.json());
188-
if (!cacheWrite) return responseObj;
235+
if (!cacheWrite || !caching) return responseObj;
189236
// first behaviour when delete cache is set to true
190237
if (toDelete) {
191-
cache.write(mutation, responseObj, true);
238+
cache.write(mutation, responseObj, searchTerms, true);
192239
return responseObj;
193240
}
194241
// second behaviour if update function provided
195242
if (update) {
196243
update(cache, responseObj);
197244
}
198245

199-
if(!responseObj.errors) cache.write(mutation, responseObj);
246+
if(!responseObj.errors) cache.write(mutation, responseObj, searchTerms);
200247
// third behaviour just for normal update (no-delete, no update function)
201248
console.log('WriteThrough - true ', responseObj);
202249
return responseObj;

0 commit comments

Comments
 (0)