🐛 Fixed superfluous DB queries on Collection save

We have a global hook for the bookshelf-relations plugin which updates the
sort_order for pivot tables when saving the parent model. This hook requires
that we fetch each row in the pivot table related to the model and then run an
update on each one. Since we have a "latest" Collection this means at least N
update queries where N is the number of Posts for a site. For large sites this
was crippling the database. We only need the sort_order to be updated for
Collections with a type of "manual". We currently don't have a way to disable
the update based on model attributes, so instead we have disabled the update for
all Collections - this is okay because 1. Collections is not released and 2. we
don't have full support for manual Collections yet anyway.
This commit is contained in:
Fabien "egg" O'Carroll 2023-08-02 14:14:54 +01:00
parent c81baebdbb
commit 2cd50d47af
2 changed files with 54 additions and 1 deletions

View File

@ -80,7 +80,7 @@ ghostBookshelf.plugin('bookshelf-relations', {
};
// CASE: disable after hook for specific relations
if (['permissions_roles', 'members_newsletters'].indexOf(existing.relatedData.joinTableName) !== -1) {
if (['permissions_roles', 'members_newsletters', 'collections_posts'].indexOf(existing.relatedData.joinTableName) !== -1) {
return Promise.resolve();
}

View File

@ -0,0 +1,53 @@
const assert = require('assert/strict');
const testUtils = require('../../utils');
const models = require('../../../core/server/models');
const db = require('../../../core/server/data/db');
describe('Collection Model', function () {
before(testUtils.teardownDb);
before(testUtils.stopGhost);
after(testUtils.teardownDb);
// This is required for the models to be initialised ???
// @TODO remove this once we have a better way of initialising models
before(testUtils.setup('users:roles', 'posts'));
describe('add', function () {
it('does not update the sort_order of the collections_posts table', async function () {
if (db?.knex?.client?.config?.client !== 'sqlite3') {
return this.skip();
}
/** @type {import('sqlite3').Database} */
const database = db.knex.client;
let didUpdateCollectionPosts = false;
function handler(/** @type {{sql: string}} */ query) {
if (query.sql.toLowerCase().includes('update `collections_posts` set `sort_order`')) {
didUpdateCollectionPosts = true;
}
}
const posts = await models.Post.findAll();
database.on('query', handler);
await models.Collection.add({
title: 'Test Collection',
slug: 'test-collection',
description: 'Test description',
type: 'manual',
filter: null,
posts: posts.toJSON().map(post => ({id: post.id})),
feature_image: null
});
database.off('query', handler);
const actual = didUpdateCollectionPosts;
const expected = false;
assert.equal(actual, expected, 'collections_posts should not have been updated');
});
});
});