-
-
Notifications
You must be signed in to change notification settings - Fork 112
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #33 from Alonsog66/master
Added session storage and clear cache functionality
- Loading branch information
Showing
5 changed files
with
91 additions
and
75 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,32 @@ | ||
import React from 'https://dev.jspm.io/[email protected]'; // from deps | ||
// import clientStorage from 'https://deno.land/x/[email protected]/ObsidianWrapper/clientStorage.js'; | ||
import React from 'https://dev.jspm.io/[email protected]'; | ||
|
||
import normalizeResult from '../src/normalize.js'; | ||
import destructureQueries from '../src/destructureQueries.js'; | ||
|
||
// Context will be used to create a custom provider for the application | ||
export const cacheContext = React.createContext(); | ||
// Declaration of custom Obsidian Wrapper | ||
function ObsidianWrapper(props) { | ||
const [cache, setCache] = React.useState({}); | ||
|
||
// Primary function, provides access to fetching and caching capabilities | ||
async function fetcher(query, options = {}) { | ||
|
||
console.log(cache); | ||
|
||
// Desctructuring of optional parameters, default values are defined and may be over written | ||
const { | ||
endpoint = '/graphql', | ||
pollInterval = null, | ||
destructure = true, | ||
sessionStore = false, | ||
} = options; | ||
if (destructure) { | ||
const obsidianSchema = window.__INITIAL_STATE__.obsidianSchema; | ||
/* COMMENT OUT THESE LINES FOR SERVER CACHE */ | ||
const deepCache = Object.assign({}, cache); | ||
const obsidianReturn = await destructureQueries(query, obsidianSchema, deepCache); | ||
const deepCache = sessionStore ? localStorage : Object.assign({}, cache); | ||
const obsidianReturn = await destructureQueries( | ||
query, | ||
obsidianSchema, | ||
deepCache | ||
); | ||
// // Conditional to check if query is stored in global cache | ||
if (obsidianReturn) { | ||
console.log('--------------'); | ||
|
@@ -36,11 +40,14 @@ function ObsidianWrapper(props) { | |
); | ||
} | ||
} else { | ||
if (cache[query]) { | ||
const checkStorage = sessionStore | ||
? JSON.parse(sessionStorage.getItem(query)) | ||
: cache[query]; | ||
if (checkStorage) { | ||
console.log('--------------'); | ||
console.log('Found it in the cache!!'); | ||
console.log('--------------'); | ||
return new Promise((resolve, reject) => resolve(cache[query])); | ||
return new Promise((resolve, reject) => resolve(checkStorage)); | ||
} | ||
} | ||
// If not found in cache, query is excecuted | ||
|
@@ -56,27 +63,33 @@ function ObsidianWrapper(props) { | |
setInterval(() => { | ||
console.log('--------------'); | ||
console.log('Fetching query with poll interval'); | ||
fetchData(query, endpoint); | ||
fetchData(query, endpoint, destructure, sessionStore); | ||
}, pollInterval); | ||
} | ||
console.log('--------------'); | ||
console.log('Fetching Data'); | ||
// Excection of fetch | ||
return await fetchData(query, endpoint, destructure); | ||
/* COMMENT OUT THESE LINES FOR SERVER CACHE */ | ||
/* COMMENT OUT THESE LINES FOR SERVER CACHE */ | ||
return new Promise((resolve, reject) => | ||
resolve(fetchData(query, endpoint, destructure, sessionStore)) | ||
); | ||
} | ||
// Function to update the global cache with new response data | ||
function updateCache(query, response) { | ||
function updateCache(query, response, sessionStore) { | ||
// Declaring new object with new data to store in cache | ||
const newObj = Object.assign(cache, { [query]: response }); | ||
|
||
// React hook to update global cache object | ||
setCache(newObj); | ||
// Can be uncommeted to store data in session storage | ||
// sessionStorage.setItem(query, JSON.stringify(response)); | ||
sessionStore | ||
? sessionStorage.setItem(query, JSON.stringify(response)) | ||
: setCache(newObj); | ||
} | ||
function clearCache() { | ||
sessionStorage.clear(); | ||
setCache({}); | ||
} | ||
|
||
// Excecutes graphql fetch request | ||
async function fetchData(query, endpoint, destructure) { | ||
async function fetchData(query, endpoint, destructure, sessionStore) { | ||
try { | ||
const respJSON = await fetch(endpoint, { | ||
method: 'POST', | ||
|
@@ -90,28 +103,36 @@ function ObsidianWrapper(props) { | |
// Excecute function to update the cache with new response | ||
if (destructure) { | ||
const obsidianSchema = window.__INITIAL_STATE__.obsidianSchema; | ||
/* COMMENT OUT THESE LINES FOR SERVER CACHE */ | ||
|
||
const deepCache = Object.assign({}, cache); | ||
normalizeResult(query, resp, obsidianSchema, deepCache) | ||
.then(updatedCache => { | ||
for (let key in updatedCache) { | ||
for (let hash in updatedCache[key]) { | ||
updateCache(hash, updatedCache[key][hash]); | ||
} | ||
} | ||
return resp; | ||
|
||
return new Promise((resolve, reject) => { | ||
resolve( | ||
normalizeResult(query, resp, obsidianSchema, deepCache).then( | ||
(updatedCache) => { | ||
for (let key in updatedCache) { | ||
for (let hash in updatedCache[key]) { | ||
updateCache(hash, updatedCache[key][hash], sessionStore); | ||
} | ||
} | ||
return resp; | ||
} | ||
) | ||
); | ||
}); | ||
/* COMMENT OUT THESE LINES FOR SERVER CACHE */ | ||
} else { | ||
updateCache(query, resp); | ||
updateCache(query, resp, sessionStore); | ||
return resp; | ||
} | ||
return resp; | ||
} catch (e) { | ||
console.log(e); | ||
} | ||
} | ||
|
||
// Returning Provider React component that allows consuming components to subscribe to context changes | ||
return <cacheContext.Provider value={{ cache, fetcher }} {...props} />; | ||
return ( | ||
<cacheContext.Provider value={{ cache, fetcher, clearCache }} {...props} /> | ||
); | ||
} | ||
// Declaration of custom hook to allow access to provider | ||
function useObsidian() { | ||
|
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,88 +1,81 @@ | ||
import { superoak } from "https://deno.land/x/[email protected]/mod.ts"; | ||
import { describe, it } from "https://deno.land/x/[email protected]/test/utils.ts"; | ||
import { expect } from "https://deno.land/x/[email protected]/test/deps.ts"; | ||
import { superoak } from 'https://deno.land/x/[email protected]/mod.ts'; | ||
import { describe, it } from 'https://deno.land/x/[email protected]/test/utils.ts'; | ||
import { expect } from 'https://deno.land/x/[email protected]/test/deps.ts'; | ||
|
||
import { app } from './server.tsx'; | ||
|
||
describe('GET request to root url', () => { | ||
it('Sends 200 Status and Content Type text/html', async ( done ) => { | ||
(await superoak(app)) | ||
.get("/") | ||
.end((err, res) => { | ||
expect(res.status).toEqual(200); | ||
expect(res.type).toEqual('text/html'); | ||
done(); | ||
}); | ||
it('Sends 200 Status and Content Type text/html', async (done) => { | ||
(await superoak(app)).get('/').end((err, res) => { | ||
expect(res.status).toEqual(200); | ||
expect(res.type).toEqual('text/html'); | ||
done(); | ||
}); | ||
}); | ||
|
||
}) | ||
}); | ||
|
||
describe('GraphQL query response testing', () => { | ||
it('getBook query succeeds', async (done:any) => { | ||
it('getBook query succeeds', async (done: any) => { | ||
(await superoak(app)) | ||
.post('/graphql') | ||
.send({query: '{getBook(id:1){ id title author }}'}) | ||
.end((err:any, res:any) => { | ||
.send({ query: '{getBook(id:1){ id title author }}' }) | ||
.end((err: any, res: any) => { | ||
console.log(res); | ||
expect(res.status).toEqual(200); | ||
expect(res.body.data.getBook.id).toEqual('1'); | ||
expect(res.body.data.getBook.title).toEqual('Lets Go'); | ||
expect(res.body.data.getBook.author).toEqual('Jeho'); | ||
setTimeout(done, 500); | ||
}) | ||
}) | ||
}); | ||
}); | ||
|
||
it('Invalid getBook query fails', async (done) => { | ||
(await superoak(app)) | ||
.post('/graphql') | ||
.send({query:'{getBook{ id title author }}'}) | ||
.send({ query: '{getBook{ id title author }}' }) | ||
.end((err, res) => { | ||
console.log('error', err) | ||
console.log('error', err); | ||
console.log(res); | ||
expect(res.status).toEqual(200); | ||
expect(res.body.errors).toBeTruthy(); | ||
done(); | ||
}) | ||
}) | ||
}); | ||
}); | ||
|
||
it('getEightBooks succeeds', async (done) => { | ||
(await superoak(app)) | ||
.post('/graphql') | ||
.send({query:'{getEightBooks(id:1){ id title author }}'}) | ||
.send({ query: '{getEightBooks(id:1){ id title author }}' }) | ||
.end((err, res) => { | ||
console.log(res); | ||
expect(res.status).toEqual(200); | ||
expect(res.body.data.getEightBooks).toHaveLength(8); | ||
setTimeout(done, 500); | ||
}) | ||
}) | ||
}) | ||
}); | ||
}); | ||
}); | ||
|
||
describe('Redis cache testing', () => { | ||
it('second query takes less than half time of first', async (done) => { | ||
let firstResTime : number; | ||
(await superoak(app)) | ||
let firstResTime: number; | ||
(await superoak(app)) | ||
.post('/graphql') | ||
.send({query: '{getBook(id:2){ id title author }}'}) | ||
.send({ query: '{getBook(id:2){ id title author }}' }) | ||
.end((err, res) => { | ||
console.log(res); | ||
firstResTime = Number(res.header['x-response-time'].slice(0, -2)); | ||
}) | ||
}); | ||
|
||
setTimeout(async () => {(await superoak(app)) | ||
setTimeout(async () => { | ||
(await superoak(app)) | ||
.post('/graphql') | ||
.send({query: '{getBook(id:2){ id title author }}'}) | ||
.send({ query: '{getBook(id:2){ id title author }}' }) | ||
.end((err, res) => { | ||
const newTime: number = res.header['x-response-time'].slice(0, -2); | ||
|
||
expect(newTime < (0.5 * firstResTime)).toBeTruthy(); | ||
expect(newTime < 0.5 * firstResTime).toBeTruthy(); | ||
setTimeout(done, 500); | ||
})}, 500) | ||
}) | ||
}) | ||
|
||
|
||
|
||
|
||
|
||
|
||
}); | ||
}, 500); | ||
}); | ||
}); |
Binary file not shown.