Skip to content

Commit

Permalink
Merge pull request #1 from djdalfaro/master
Browse files Browse the repository at this point in the history
Alias feature implemented for server-side caching
  • Loading branch information
aswilson87 authored Feb 20, 2021
2 parents 6de2e1c + af9c066 commit 2cd2791
Show file tree
Hide file tree
Showing 16 changed files with 249 additions and 12 deletions.
6 changes: 5 additions & 1 deletion .env
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
POSTGRES_URI=postgres://zjxjnswd:Wh7KJIyXiEy5QyhzXUMK38ykEtYH_9QZ@lallah.db.elephantsql.com:5432/zjxjnswd
PG_PORT=5432
PG_USER=uiikgqgj
PG_DATABASE=uiikgqgj
PG_PASSWORD=cSjcLEFvsuAb7Q3bc6O5p2LYbyjWlw5t
PG_HOSTNAME=suleiman.db.elephantsql.com
REDIS_HOST=localhost
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
dump.rdb
.DS_Store
.env
server.tsx
server2.tsx
1 change: 1 addition & 0 deletions src/CacheClassBrowser.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export default class Cache {
async cacheRead(hash) {
return this.storage[hash];
}

async cacheWrite(hash, value) {
this.storage[hash] = value;
}
Expand Down
8 changes: 5 additions & 3 deletions src/CacheClassServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,14 @@ export class Cache {
if (rootQuery[queryHash]) {
// get the hashs to populate from the existent query in the cache
const arrayHashes = rootQuery[queryHash];
// Determines responseObject property labels - use alias if applicable, otherwise use name
const respObjProp = queries[query].alias ?? queries[query].name;
// invoke populateAllHashes and add data objects to the response object for each input query
responseObject[queries[query].name] = await this.populateAllHashes(
responseObject[respObjProp] = await this.populateAllHashes(
arrayHashes,
queries[query].fields
);
if (!responseObject[queries[query].name]) return undefined;
if (!responseObject[respObjProp]) return undefined;

// no match with ROOT_QUERY return null or ...
} else {
Expand Down Expand Up @@ -84,7 +86,6 @@ export class Cache {
// cache read/write helper methods
async cacheRead(hash) {
// returns value from either object cache or cache || 'DELETED' || undefined

if (this.context === 'client') {
return this.storage[hash];
} else {
Expand Down Expand Up @@ -112,6 +113,7 @@ export class Cache {
} else {
value = JSON.stringify(value);
await redis.setex(hash, 30, value);
let hashedQuery = await redis.get(hash);
}
}
async cacheDelete(hash) {
Expand Down
28 changes: 28 additions & 0 deletions src/destructure.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export function findQueryStrings(queryStrings) {
}
return result;
}

// helper function to create a queries object from an array of query strings
export function createQueriesObj(arrayOfQueryStrings, typePropName) {
// define a new empty result object
Expand All @@ -76,6 +77,7 @@ export function createQueriesObj(arrayOfQueryStrings, typePropName) {
// push the finished query object into the queries/mutations array on the result object
queriesObj[typePropName].push(queryObj);
});

return queriesObj;
}
// helper function that returns an object with a query string split into multiple parts
Expand All @@ -88,12 +90,35 @@ export function splitUpQueryStr(queryStr) {
// checks to see if there are no arguments
if (argsStartIndex === -1 || firstBraceIndex < argsStartIndex) {
queryObj.name = queryStr.substring(0, firstBraceIndex).trim();
// // Checks if there is an alias
if (queryObj.name.includes(':')) {
// sets index of alias marker :
const aliasIndex = queryObj.name.indexOf(':');
// sets alias
queryObj.alias = queryObj.name.substring(0, aliasIndex).trim();
// shortens name to exclude alias
queryObj.name = queryObj.name
.substring(aliasIndex + 1, firstBraceIndex)
.trim();
}
queryObj.arguments = '';
queryObj.fields = queryStr.substring(firstBraceIndex);

return queryObj;
}
// finds the query name string and assigns it
queryObj.name = queryStr.substring(0, argsStartIndex).trim();
// Checks if there is an alias
if (queryObj.name.includes(':')) {
// sets index of alias marker :
const aliasIndex = queryObj.name.indexOf(':');
// sets alias
queryObj.alias = queryObj.name.substring(0, aliasIndex).trim();
// shortens name to exclude alias
queryObj.name = queryObj.name
.substring(aliasIndex + 1, firstBraceIndex)
.trim();
}
// begin iterating through the queryString at the beginning of the arguments
for (let i = argsStartIndex; i < queryStr.length; i += 1) {
const char = queryStr[i];
Expand All @@ -108,6 +133,7 @@ export function splitUpQueryStr(queryStr) {
if (argsString === '()') argsString = '';
queryObj.arguments = argsString;
queryObj.fields = queryStr.substring(i + 1).trim();

return queryObj;
}
}
Expand Down Expand Up @@ -142,6 +168,7 @@ export function findQueryFields(fieldsStr) {
// finding a non-whitespace character after the end of fieldname indicates the field is scalar or meta
if (char.match(/\S/) && foundEndOfFieldName) {
fieldsObj[fieldCache] = fieldCache === '__typename' ? 'meta' : 'scalar';

fieldCache = '';
foundEndOfFieldName = false;
}
Expand All @@ -150,6 +177,7 @@ export function findQueryFields(fieldsStr) {
// adds current non-whitespace character in fieldCache
if (char.match(/\S/)) fieldCache += char;
}

return fieldsObj;
}

Expand Down
2 changes: 2 additions & 0 deletions src/insertTypenames.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export function insertTypenames(queryOperationStr) {
}
return newQueryStr;
}

// helper function to add typenames to fieldsStr where needed
export function addTypenamesToFieldsStr(fieldsStr) {
let newFieldsStr = fieldsStr;
Expand Down Expand Up @@ -62,6 +63,7 @@ export function addTypenamesToFieldsStr(fieldsStr) {
}
return newFieldsStr;
}

// helper function to find the partner closing brace
export function findClosingBrace(str, index) {
let bracePairs = 0;
Expand Down
9 changes: 5 additions & 4 deletions src/normalize.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,21 +81,22 @@ export default function normalizeResult(queryObj, resultObj, deleteFlag) {
}
}
}

return result;
}

// creates the hashes for query requests and stores the reference has that will be stored in result
// creates the hashes for query requests and stores the reference hash that will be stored in result
function createRootQuery(queryObjArr, resultObj) {
const output = {};
queryObjArr.forEach((query) => {
// if query has an alias declare it
const alias = query.alias ?? null;
const name = query.name;
const args = query.arguments;
const queryHash = name + args;

const result = resultObj.data[alias] ?? resultObj.data[name];
// iterate thru the array of current query response
// and store the hash of that response in an array
const result = resultObj.data[name];

if (Array.isArray(result)) {
const arrOfHashes = [];
result.forEach((obj) => {
Expand Down
2 changes: 1 addition & 1 deletion src/obsidian.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export async function ObsidianRouter<T>({
if (useCache) {
// Send query off to be destructured and found in Redis if possible //
const obsidianReturn = await cache.read(body.query);

console.log("retrieved from cache", obsidianReturn);
if (obsidianReturn) {
response.status = 200;
response.body = obsidianReturn;
Expand Down
9 changes: 9 additions & 0 deletions test_files/rhum_test_files/destructure_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ Rhum.testPlan('destructure.ts', () => {
Rhum.asserts.assertEquals(test.createQueriesObjResultsData, results);
});
Rhum.testCase('findQueryFields test', () => {
console.log(test.findQueryFieldsTestData);
const results = findQueryFields(test.findQueryFieldsTestData);
console.log(results);
Rhum.asserts.assertEquals(test.findQueryFieldsResultData, results);
});
Rhum.testCase('findClosingBrace test', () => {
Expand All @@ -48,6 +50,13 @@ Rhum.testPlan('destructure.ts', () => {
Rhum.asserts.assertEquals(test.allActionActorsTestResult, result);
});
});

Rhum.testSuite('destructure alias query tests', () => {
Rhum.testCase('destructure multi alias query - input / non input', () => {
const result = destructureQueries(test.newAliasTestQuery);
Rhum.asserts.assertEquals(test.newAliasTestResult, result);
});
});
});

Rhum.run();
10 changes: 10 additions & 0 deletions test_files/rhum_test_files/insertTypenames_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,15 @@ Rhum.testPlan('insertTypenames.js', () => {
}
);
});

Rhum.testSuite('insertTypenames()', () => {
Rhum.testCase(
'should add __typenames meta field to graphql alias query',
() => {
const result = insertTypenames(test.newAliasTestQuery);
Rhum.asserts.assertEquals(result, test.newAliasTestResult);
}
);
});
});
Rhum.run();
9 changes: 9 additions & 0 deletions test_files/rhum_test_files/normalize_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ Rhum.testPlan('normalize.ts', () => {
}
);
});
Rhum.testSuite('normalizeAliasTestSuite', () => {
Rhum.testCase(
'expected result to equal object with ROOT_QUERY and hash:value pairs',
async () => {
const result = normalizeResult(test.aliasTestQueryObj, test.aliasTestResult);
Rhum.asserts.assertEquals(result, test.aliasTestRootHash);
}
);
});
});

Rhum.run();
Expand Down
10 changes: 10 additions & 0 deletions test_files/rhum_test_files/writeCache_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
*/

import Cache from '../../src/CacheClassBrowser.js';
import {Cache as CacheServer} from '../../src/CacheClassServer.js';
import { Rhum } from 'https://deno.land/x/rhum@v1.1.4/mod.ts';
import { test } from '../test_variables/writeCache_variables.ts';

Expand Down Expand Up @@ -38,6 +39,15 @@ Rhum.testPlan('write method on Cache class', () => {
Rhum.asserts.assertEquals(test.originalCache, cache.storage);
}
);
// Rhum.testCase(
// 'alias test case',
// async () => {
// const cache = new CacheServer(test.originalCache);
// await cache.write(test.aliasQuery, test.aliasResponse);
// await console.log(cache.storage);
// Rhum.asserts.assertEquals(cache.storage, test.originalCache);
// }
// );
});
});
Rhum.run();
Expand Down
68 changes: 67 additions & 1 deletion test_files/test_variables/destructure_variables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export const test = {
}
}
}
}
`,

allActorsTestResult: {
Expand Down Expand Up @@ -218,4 +218,70 @@ export const test = {
}`,

findClosingBraceResultData: 90,

findTwoActorsAlias: `
query TwoActors {
harrisonActor: actors(id: 00) {
firstName
lastName
films {
__typename
id
title
}
}
hammelActor: actors(id: 01) {
firstName
lastName
films {
__typename
id
title
}
}
}
`,
findTwoActorsAliasTestResult: {
queries: [
{
name: "actors",
alias: "harrisonActor",
arguments: "(id:00)",
fields: { firstName: "scalar", lastName: "scalar", films: { __typename: 'meta', id: 'scalar', title: 'scalar' } }
},
{
name: "actors",
alias: "hammelActor",
arguments: "(id:01)",
fields: { firstName: "scalar", lastName: "scalar", films: { __typename: 'meta', id: 'scalar', title: 'scalar' } }
}
]
},

newAliasTestQuery: `
query twoHeros {
empireHero: hero(episode: EMPIRE) {
name
}
jediHero: hero(episode: JEDI) {
name
}
}`,

newAliasTestResult:{
queries: [
{
name: "hero",
alias: "empireHero",
arguments: "(episode:EMPIRE)",
fields: { name: "scalar" }
},
{
name: "hero",
alias: "jediHero",
arguments: "(episode:JEDI)",
fields: { name: "scalar" }
}
]
}
};
12 changes: 12 additions & 0 deletions test_files/test_variables/insertTypenames_variables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,16 @@ export const test = {
'{ __typename id title genre actors { id firstName lastName } }',
fieldsStrOutput:
'{ __typename id title genre actors { __typename id firstName lastName } }',

newAliasTestQuery: `
query twoHeros {
empireHero: hero(episode: EMPIRE) {
name
}
jediHero: hero(episode: JEDI) {
name
}
}`,

newAliasTestResult: `query twoHeros { empireHero: hero(episode: EMPIRE) { __typename name } jediHero: hero(episode: JEDI) { __typename name } }`,
};
Loading

0 comments on commit 2cd2791

Please sign in to comment.