Revert "Optimised queries made by get helper for posts"

no-issue

This was incorrectly merged - reverting until the work is complete
This commit is contained in:
Fabien O'Carroll 2024-03-14 09:16:50 -04:00 committed by Fabien 'egg' O'Carroll
parent a309a29ef6
commit 39da5a1f88
2 changed files with 2 additions and 158 deletions

View File

@ -11,7 +11,6 @@ const Sentry = require('@sentry/node');
const _ = require('lodash'); const _ = require('lodash');
const jsonpath = require('jsonpath'); const jsonpath = require('jsonpath');
const nqlLang = require('@tryghost/nql-lang');
const messages = { const messages = {
mustBeCalledAsBlock: 'The {\\{{helperName}}} helper must be called as a block. E.g. {{#{helperName}}}...{{/{helperName}}}', mustBeCalledAsBlock: 'The {\\{{helperName}}} helper must be called as a block. E.g. {{#{helperName}}}...{{/{helperName}}}',
@ -132,54 +131,6 @@ function parseOptions(globals, data, options) {
*/ */
async function makeAPICall(resource, controllerName, action, apiOptions) { async function makeAPICall(resource, controllerName, action, apiOptions) {
const controller = api[controllerName]; const controller = api[controllerName];
let makeRequest = () => controller[action](apiOptions);
// Only do the optimisation on posts
if (resource === 'posts' && apiOptions.filter) {
try {
const parsedFilter = nqlLang.parse(apiOptions.filter);
// Support either `id:blah` or `id:blah+other:stuff`
if (parsedFilter.$and || parsedFilter.id) {
const queries = parsedFilter.$and || [parsedFilter.id];
for (const query of queries) {
if ('id' in query) {
if ('$ne' in query.id) {
// This checks that there is only one occurence of a negative id filter
// So we know it's safe to use the `replace` method
if (apiOptions.filter.split('id:-').length === 2) {
const idToFilter = query.id.$ne;
// The default limit is 15, the addition order is to cast apiOptions.limit to a number
let limit = apiOptions.limit;
limit = apiOptions.limit && apiOptions.limit !== 'all' ? 1 + apiOptions.limit : 16;
// We replace with id:-null so we don't have to deal with leading/trailing AND operators
const filter = apiOptions.filter.replace(/id:-[a-f0-9A-F]{24}/, 'id:-null');
makeRequest = async () => {
const result = await controller[action]({
...apiOptions,
limit,
filter
});
return {
...result,
posts: result?.posts?.filter((post) => {
return post.id !== idToFilter;
}).slice(0, limit - 1) || []
};
};
}
}
}
}
}
} catch (err) {
logging.warn(err);
}
}
let timer; let timer;
@ -190,7 +141,7 @@ async function makeAPICall(resource, controllerName, action, apiOptions) {
const logLevel = config.get('optimization:getHelper:timeout:level') || 'error'; const logLevel = config.get('optimization:getHelper:timeout:level') || 'error';
const threshold = config.get('optimization:getHelper:timeout:threshold'); const threshold = config.get('optimization:getHelper:timeout:threshold');
const apiResponse = makeRequest(); const apiResponse = controller[action](apiOptions);
const timeout = new Promise((resolve) => { const timeout = new Promise((resolve) => {
timer = setTimeout(() => { timer = setTimeout(() => {
@ -210,7 +161,7 @@ async function makeAPICall(resource, controllerName, action, apiOptions) {
response = await Promise.race([apiResponse, timeout]); response = await Promise.race([apiResponse, timeout]);
clearTimeout(timer); clearTimeout(timer);
} else { } else {
response = await makeRequest(); response = await controller[action](apiOptions);
} }
return response; return response;

View File

@ -1,4 +1,3 @@
const assert = require('assert/strict');
const should = require('should'); const should = require('should');
const sinon = require('sinon'); const sinon = require('sinon');
const testUtils = require('../../utils'); const testUtils = require('../../utils');
@ -99,112 +98,6 @@ describe('e2e {{#get}} helper', function () {
locals = {root: {_locals: {}}}; locals = {root: {_locals: {}}};
}); });
describe('Filter optimisation', function () {
it('Returns the correct posts with a solo negative filter', async function () {
await get.call({}, 'posts', {
hash: {
limit: 1
},
data: {},
locals,
fn,
inverse
});
const firstPostUsually = fn.firstCall.args[0].posts[0];
await get.call({}, 'posts', {
hash: {
filter: `id:-${firstPostUsually.id}`,
limit: 5
},
data: {},
locals,
fn,
inverse
});
assert.equal(fn.secondCall.args[0].posts.length, 5);
const foundFilteredPost = fn.secondCall.args[0].posts.find(post => post.id === firstPostUsually.id);
assert.equal(foundFilteredPost, undefined);
});
it('Returns the correct posts with a sandwiched negative filter', async function () {
await get.call({}, 'posts', {
hash: {
filter: `tag:-hash-hidden+visibility:public`,
limit: 1
},
data: {},
locals,
fn,
inverse
});
const firstPostUsually = fn.firstCall.args[0].posts[0];
await get.call({}, 'posts', {
hash: {
filter: `visibility:public+id:-${firstPostUsually.id}+tag:-hash-hidden`,
limit: 5
},
data: {},
locals,
fn,
inverse
});
assert.equal(fn.secondCall.args[0].posts.length, 5);
const foundFilteredPost = fn.secondCall.args[0].posts.find(post => post.id === firstPostUsually.id);
assert.equal(foundFilteredPost, undefined);
});
it('Returns the correct posts with a prefix negative filter', async function () {
await get.call({}, 'posts', {
hash: {
filter: `tag:-hash-hidden`,
limit: 1
},
data: {},
locals,
fn,
inverse
});
const firstPostUsually = fn.firstCall.args[0].posts[0];
await get.call({}, 'posts', {
hash: {
filter: `id:-${firstPostUsually.id}+tag:-hash-hidden`,
limit: 5
},
data: {},
locals,
fn,
inverse
});
assert.equal(fn.secondCall.args[0].posts.length, 5);
const foundFilteredPost = fn.secondCall.args[0].posts.find(post => post.id === firstPostUsually.id);
assert.equal(foundFilteredPost, undefined);
});
it('Returns the correct posts with a suffix negative filter', async function () {
await get.call({}, 'posts', {
hash: {
filter: `tag:-hash-hidden`,
limit: 1
},
data: {},
locals,
fn,
inverse
});
const firstPostUsually = fn.firstCall.args[0].posts[0];
await get.call({}, 'posts', {
hash: {
filter: `tag:-hash-hidden+id:-${firstPostUsually.id}`,
limit: 5
},
data: {},
locals,
fn,
inverse
});
assert.equal(fn.secondCall.args[0].posts.length, 5);
const foundFilteredPost = fn.secondCall.args[0].posts.find(post => post.id === firstPostUsually.id);
assert.equal(foundFilteredPost, undefined);
});
});
describe('{{access}} property', function () { describe('{{access}} property', function () {
let member; let member;