Skip to content

Commit f3cc217

Browse files
committed
cache existence checks and improve existence check query performance
1 parent e790282 commit f3cc217

File tree

1 file changed

+31
-3
lines changed

1 file changed

+31
-3
lines changed

graphql-server/drivers/arangodb/driver.js

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ async function init(args) {
6868
let drop = args.drop || false;
6969
disableDirectivesChecking = args['disableDirectivesChecking'] || false;
7070
disableEdgeValidation = args['disableEdgeValidation'] || false;
71+
cachingEnabled = args['cache'] === false ? false : true;
7172
db = new arangojs.Database({ url: url });
7273

7374
// wait for ArangoDB
@@ -809,8 +810,17 @@ function deleteObject(isRoot, ctxt, varOrID, typeToDelete, info, resVar = null)
809810

810811
// directives handling
811812
addFinalDirectiveChecksForType(ctxt, typeToDelete, aql`${asAQLVar(resVar)}._id`, info.schema);
813+
814+
// invalidate cache
815+
ctxt.trans.code.push(`
816+
// remove from cache
817+
cacheKey = ${idVar};
818+
delete cache[cacheKey];
819+
`);
820+
812821
// return promises for roots and null for nested result
813822
ctxt.trans.code.push(`}`);
823+
814824
return isRoot ? getResult(ctxt, info, resVar) : null;
815825
}
816826

@@ -1246,7 +1256,7 @@ function validateEdge(ctxt, source, sourceType, sourceField, target, targetType,
12461256
* @param typeOrInterface
12471257
* @param schema
12481258
*/
1249-
function exists(ctxt, id, typeOrInterface, schema) {
1259+
function exists(ctxt, varOrID, typeOrInterface, schema) {
12501260
let aqlCollectionVars = [];
12511261
if (graphql.isInterfaceType(typeOrInterface) || graphql.isUnionType(typeOrInterface)) {
12521262
for (let possibleType of Object.values(schema.getPossibleTypes(typeOrInterface))) {
@@ -1255,7 +1265,22 @@ function exists(ctxt, id, typeOrInterface, schema) {
12551265
} else {
12561266
aqlCollectionVars.push(asAQLVar(getCollectionVar(typeOrInterface.name)));
12571267
}
1258-
ctxt.trans.code.push(`if(!db._query(aql\`FOR doc IN FLATTEN(FOR i IN [${aqlCollectionVars.join(', ')}] RETURN i) FILTER doc._id == ${id} RETURN doc\`).next()){ throw \`Object '${id}' does not exist as instance of ${typeOrInterface}\`; }`);
1268+
1269+
let queries = [];
1270+
for(let collection of aqlCollectionVars){
1271+
queries.push(`LENGTH(FOR d IN ${collection} FILTER d._id == ${varOrID} LIMIT 1 RETURN true) > 0`);
1272+
}
1273+
1274+
// check cache
1275+
ctxt.trans.code.push(`cacheKey = ${varOrID.substring(2,varOrID.length-1)};
1276+
cache[cacheKey] = cache[cacheKey] === undefined ? [] : cache[cacheKey];
1277+
if(${cachingEnabled} && cache[cacheKey].includes('${typeOrInterface}')){
1278+
// skip cached
1279+
} else if(!db._query(aql\`RETURN ${queries.join(' || ')}\`).next()){
1280+
throw \`Object '${varOrID}' does not exist as instance of ${typeOrInterface}\`;
1281+
}
1282+
cache[cacheKey] = '${typeOrInterface}';
1283+
`);
12591284
}
12601285

12611286
/**
@@ -1283,7 +1308,9 @@ function initTransaction(ctxt) {
12831308
code: [
12841309
'const db = require("@arangodb").db;',
12851310
'const {aql} = require("@arangodb");',
1286-
'let result = Object.create(null);'
1311+
'let result = Object.create(null);',
1312+
'let cache = Object.create(null);',
1313+
'let cacheKey = null;'
12871314
],
12881315
finalConstraintChecks: [],
12891316
exportedVariables: {}
@@ -1312,6 +1339,7 @@ async function executeTransaction(ctxt) {
13121339

13131340
try {
13141341
let action = `function(params){\n\t${ctxt.trans.code.join('\n\t')}\n\treturn result;\n}`;
1342+
13151343
console.debug(action);
13161344
console.debug(ctxt.trans.params);
13171345
ctxt.trans.results = await db.transaction(

0 commit comments

Comments
 (0)