From 16ce639df591b537c884d0745d184eb30a6b8c82 Mon Sep 17 00:00:00 2001 From: Marc-Roig Date: Tue, 18 Apr 2023 12:32:04 +0200 Subject: [PATCH 1/9] feat: remove orphaned persisted tables --- packages/core/database/lib/schema/diff.js | 26 +++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/packages/core/database/lib/schema/diff.js b/packages/core/database/lib/schema/diff.js index 96f7018621..1aef4e806d 100644 --- a/packages/core/database/lib/schema/diff.js +++ b/packages/core/database/lib/schema/diff.js @@ -344,6 +344,13 @@ module.exports = (db) => { } } + const parsePersistedTable = (persistedTable) => { + if (typeof persistedTable === 'string') { + return persistedTable; + } + return persistedTable.table; + }; + const persistedTables = helpers.hasTable(srcSchema, 'strapi_core_store_settings') ? (await strapi.store.get({ type: 'core', @@ -351,12 +358,19 @@ module.exports = (db) => { })) ?? [] : []; + const reservedTables = [...RESERVED_TABLE_NAMES, ...persistedTables.map(parsePersistedTable)]; + for (const srcTable of srcSchema.tables) { - if ( - !helpers.hasTable(destSchema, srcTable.name) && - ![...RESERVED_TABLE_NAMES, ...persistedTables].includes(srcTable.name) - ) { - removedTables.push(srcTable); + if (!helpers.hasTable(destSchema, srcTable.name) && !reservedTables.includes(srcTable.name)) { + const dependencies = persistedTables + .filter((table) => { + return table?.dependsOn?.some((dep) => dep.table === srcTable.name); + }) + .map((table) => { + return srcSchema.tables.find((t) => t.name === table.table); + }); + + removedTables.push(srcTable, ...dependencies); } } @@ -369,7 +383,7 @@ module.exports = (db) => { added: addedTables, updated: updatedTables, unchanged: unchangedTables, - removed: removedTables, + removed: [...removedTables], }, }, }; From 71dce1dcf17afcf823daabe94596501857752678 Mon Sep 17 00:00:00 2001 From: Marc-Roig Date: Tue, 18 Apr 2023 17:00:42 +0200 Subject: [PATCH 2/9] feat: store dependent tables on persisted table --- .../admin/ee/server/utils/persisted-tables.js | 85 ++++++++++++++++--- 1 file changed, 72 insertions(+), 13 deletions(-) diff --git a/packages/core/admin/ee/server/utils/persisted-tables.js b/packages/core/admin/ee/server/utils/persisted-tables.js index bff71a881b..7df2385f7b 100644 --- a/packages/core/admin/ee/server/utils/persisted-tables.js +++ b/packages/core/admin/ee/server/utils/persisted-tables.js @@ -1,5 +1,19 @@ 'use strict'; +const { differenceWith, isEqual } = require('lodash/fp'); + +/** + * Transform table name to the object format + * @param {Array }>} table + * @returns Array<{ table: string; dependsOn?: Array<{ table: string;}> }> + */ +const transformTableName = (table) => { + if (typeof table === 'string') { + return { name: table }; + } + return table; +}; + /** * Finds all tables in the database matching the regular expression * @param {Object} ctx @@ -16,22 +30,59 @@ async function findTables({ strapi }, regex) { * Add tables name to the reserved tables in core store * @param {Object} ctx * @param {Strapi} ctx.strapi - * @param {string[]} tableNames + * @param {Array }>} tableNames * @return {Promise} */ async function addPersistTables({ strapi }, tableNames) { const persistedTables = await getPersistedTables({ strapi }); - const notReservedTableNames = tableNames.filter((name) => !persistedTables.includes(name)); + const tables = tableNames.map(transformTableName); - if (!notReservedTableNames.length) { + // Get new tables to be persisted, remove tables if they already were persisted + const notPersistedTableNames = differenceWith(isEqual, tables, persistedTables); + // Remove tables that are going to be changed + const tablesToPersist = differenceWith( + (t1, t2) => t1.name === t2.name, + persistedTables, + notPersistedTableNames + ); + + if (!notPersistedTableNames.length) { return; } - persistedTables.push(...notReservedTableNames); + tablesToPersist.push(...notPersistedTableNames); await strapi.store.set({ type: 'core', key: 'persisted_tables', - value: persistedTables, + value: tablesToPersist, + }); +} + +/** + * Remove tables name from the reserved tables in core store + * @param {Object} ctx + * @param {Strapi} ctx.strapi + * @param {Array} tableNames + * @return {Promise} + */ +async function removePersistedTables({ strapi }, tableNames) { + const persistedTables = await getPersistedTables({ strapi }); // Array<{name: string, dependsOn: Array<{name: string}>}> + + // Using differenceWith instead of filter to avoid mutating the original array + const newPersistedTables = differenceWith( + (t1, t2) => t1.name === t2, + persistedTables, + tableNames + ); + + if (newPersistedTables.length === persistedTables.length) { + return; + } + + await strapi.store.set({ + type: 'core', + key: 'persisted_tables', + value: newPersistedTables, }); } @@ -42,10 +93,12 @@ async function addPersistTables({ strapi }, tableNames) { * @returns {Promise} */ const getPersistedTables = async ({ strapi }) => - (await strapi.store.get({ - type: 'core', - key: 'persisted_tables', - })) ?? []; + ( + await strapi.store.get({ + type: 'core', + key: 'persisted_tables', + }) + ).map(transformTableName) ?? []; /** * Add all table names that start with a prefix to the reserved tables in @@ -62,19 +115,25 @@ const persistTablesWithPrefix = async (tableNamePrefix) => { }; /** - * Add all table names that end with a suffix to the reserved tables in core store + * Remove all table names that end with a suffix from the reserved tables in core store * @param {string} tableNameSuffix * @return {Promise} */ -const persistTablesWithSuffix = async (tableNameSuffix) => { +const removePersistedTablesWithSuffix = async (tableNameSuffix) => { const tableNameRegex = new RegExp(`.*${tableNameSuffix}$`); const tableNames = await findTables({ strapi }, tableNameRegex); + await removePersistedTables({ strapi }, tableNames); +}; - await addPersistTables({ strapi }, tableNames); +const persistTable = async (tableName, dependsOn) => { + await addPersistTables({ strapi }, [ + { name: tableName, dependsOn: dependsOn?.map((depTableName) => ({ name: depTableName })) }, + ]); }; module.exports = { persistTablesWithPrefix, - persistTablesWithSuffix, + removePersistedTablesWithSuffix, + persistTable, findTables, }; From fcf10199a1d3eadf1ed0228b7b82e407ab6f112f Mon Sep 17 00:00:00 2001 From: Marc-Roig Date: Tue, 18 Apr 2023 17:00:53 +0200 Subject: [PATCH 3/9] chore: rename persisted table fields --- packages/core/database/lib/schema/diff.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/core/database/lib/schema/diff.js b/packages/core/database/lib/schema/diff.js index 1aef4e806d..67ef477afc 100644 --- a/packages/core/database/lib/schema/diff.js +++ b/packages/core/database/lib/schema/diff.js @@ -348,7 +348,7 @@ module.exports = (db) => { if (typeof persistedTable === 'string') { return persistedTable; } - return persistedTable.table; + return persistedTable.name; }; const persistedTables = helpers.hasTable(srcSchema, 'strapi_core_store_settings') @@ -364,10 +364,10 @@ module.exports = (db) => { if (!helpers.hasTable(destSchema, srcTable.name) && !reservedTables.includes(srcTable.name)) { const dependencies = persistedTables .filter((table) => { - return table?.dependsOn?.some((dep) => dep.table === srcTable.name); + return table?.dependsOn?.some((table) => table.name === srcTable.name); }) - .map((table) => { - return srcSchema.tables.find((t) => t.name === table.table); + .map((dependsOnTable) => { + return srcSchema.tables.find((srcTable) => srcTable.name === dependsOnTable.name); }); removedTables.push(srcTable, ...dependencies); From 4c82c1149691278a3f71e7d9b704390e6675576e Mon Sep 17 00:00:00 2001 From: Marc-Roig Date: Tue, 18 Apr 2023 17:01:32 +0200 Subject: [PATCH 4/9] feat: persist tables when assigning content type rw stage --- .../server/services/review-workflows/review-workflows.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/core/admin/ee/server/services/review-workflows/review-workflows.js b/packages/core/admin/ee/server/services/review-workflows/review-workflows.js index 7001a98ec0..6cb5aa6ee2 100644 --- a/packages/core/admin/ee/server/services/review-workflows/review-workflows.js +++ b/packages/core/admin/ee/server/services/review-workflows/review-workflows.js @@ -10,6 +10,7 @@ const defaultWorkflow = require('../../constants/default-workflow.json'); const { ENTITY_STAGE_ATTRIBUTE } = require('../../constants/workflows'); const { getDefaultWorkflow } = require('../../utils/review-workflows'); +const { persistTable, removePersistedTablesWithSuffix } = require('../../utils/persisted-tables'); async function initDefaultWorkflow({ workflowsService, stagesService, strapi }) { const wfCount = await workflowsService.count(); @@ -73,12 +74,20 @@ function enableReviewWorkflow({ strapi }) { const stagesService = getService('stages', { strapi }); const up = async (contentTypeUID) => { + // Persist the stage join table + const { attributes, tableName } = strapi.db.metadata.get(contentTypeUID); + const joinTableName = attributes[ENTITY_STAGE_ATTRIBUTE].joinTable.name; + await persistTable(joinTableName, [tableName]); + + // Update CT entities stage return stagesService.updateEntitiesStage(contentTypeUID, { fromStageId: null, toStageId: firstStage.id, }); }; + await removePersistedTablesWithSuffix('_strapi_review_workflows_stage_links'); + return pipe([ getContentTypeUIDsWithActivatedReviewWorkflows, // Iterate over UIDs to extend the content-type From 4b5106d606895cee0a62d405132d2ba9d55e000e Mon Sep 17 00:00:00 2001 From: Marc-Roig Date: Tue, 18 Apr 2023 17:01:58 +0200 Subject: [PATCH 5/9] feat: do not persist tables with suffix --- packages/core/admin/ee/server/bootstrap.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/core/admin/ee/server/bootstrap.js b/packages/core/admin/ee/server/bootstrap.js index 7032a2b3ef..678ce883e9 100644 --- a/packages/core/admin/ee/server/bootstrap.js +++ b/packages/core/admin/ee/server/bootstrap.js @@ -5,7 +5,7 @@ const { features } = require('@strapi/strapi/lib/utils/ee'); const executeCEBootstrap = require('../../server/bootstrap'); const { getService } = require('../../server/utils'); const actions = require('./config/admin-actions'); -const { persistTablesWithPrefix, persistTablesWithSuffix } = require('./utils/persisted-tables'); +const { persistTablesWithPrefix } = require('./utils/persisted-tables'); module.exports = async () => { const { actionProvider } = getService('permission'); @@ -22,7 +22,6 @@ module.exports = async () => { if (features.isEnabled('review-workflows')) { await persistTablesWithPrefix('strapi_workflows'); - await persistTablesWithSuffix('_strapi_review_workflows_stage_links'); const { bootstrap: rwBootstrap } = getService('review-workflows'); From bd57c683af886bf2fad792975226eee35f7d0206 Mon Sep 17 00:00:00 2001 From: Marc-Roig Date: Tue, 18 Apr 2023 17:04:46 +0200 Subject: [PATCH 6/9] fix: typo --- packages/core/database/lib/schema/diff.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/database/lib/schema/diff.js b/packages/core/database/lib/schema/diff.js index 67ef477afc..ef3aaaa679 100644 --- a/packages/core/database/lib/schema/diff.js +++ b/packages/core/database/lib/schema/diff.js @@ -383,7 +383,7 @@ module.exports = (db) => { added: addedTables, updated: updatedTables, unchanged: unchangedTables, - removed: [...removedTables], + removed: removedTables, }, }, }; From 398491f0c3301bd8fc075cdc9a105fef30f0842d Mon Sep 17 00:00:00 2001 From: Marc-Roig Date: Tue, 18 Apr 2023 17:09:49 +0200 Subject: [PATCH 7/9] fix: remove persisted table comment --- packages/core/admin/ee/server/utils/persisted-tables.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/admin/ee/server/utils/persisted-tables.js b/packages/core/admin/ee/server/utils/persisted-tables.js index 7df2385f7b..0382a07e2e 100644 --- a/packages/core/admin/ee/server/utils/persisted-tables.js +++ b/packages/core/admin/ee/server/utils/persisted-tables.js @@ -68,7 +68,7 @@ async function addPersistTables({ strapi }, tableNames) { async function removePersistedTables({ strapi }, tableNames) { const persistedTables = await getPersistedTables({ strapi }); // Array<{name: string, dependsOn: Array<{name: string}>}> - // Using differenceWith instead of filter to avoid mutating the original array + // Get new tables to be persisted, remove tables if they already were persisted const newPersistedTables = differenceWith( (t1, t2) => t1.name === t2, persistedTables, From 8ba81e5c87a496759a417a8b8c4e3164f9555ca8 Mon Sep 17 00:00:00 2001 From: Marc-Roig Date: Tue, 18 Apr 2023 17:15:00 +0200 Subject: [PATCH 8/9] fix: remove comment --- packages/core/admin/ee/server/utils/persisted-tables.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/admin/ee/server/utils/persisted-tables.js b/packages/core/admin/ee/server/utils/persisted-tables.js index 0382a07e2e..bd6e89fcfb 100644 --- a/packages/core/admin/ee/server/utils/persisted-tables.js +++ b/packages/core/admin/ee/server/utils/persisted-tables.js @@ -66,7 +66,7 @@ async function addPersistTables({ strapi }, tableNames) { * @return {Promise} */ async function removePersistedTables({ strapi }, tableNames) { - const persistedTables = await getPersistedTables({ strapi }); // Array<{name: string, dependsOn: Array<{name: string}>}> + const persistedTables = await getPersistedTables({ strapi }); // Get new tables to be persisted, remove tables if they already were persisted const newPersistedTables = differenceWith( From 8da6342bde53f0d0c1791a828f1c1b5c68e5320e Mon Sep 17 00:00:00 2001 From: Marc-Roig Date: Tue, 18 Apr 2023 17:17:58 +0200 Subject: [PATCH 9/9] chore: refactor getPersistedTables --- .../admin/ee/server/utils/persisted-tables.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/core/admin/ee/server/utils/persisted-tables.js b/packages/core/admin/ee/server/utils/persisted-tables.js index bd6e89fcfb..698350ab9c 100644 --- a/packages/core/admin/ee/server/utils/persisted-tables.js +++ b/packages/core/admin/ee/server/utils/persisted-tables.js @@ -92,13 +92,15 @@ async function removePersistedTables({ strapi }, tableNames) { * @param {Strapi} ctx.strapi * @returns {Promise} */ -const getPersistedTables = async ({ strapi }) => - ( - await strapi.store.get({ - type: 'core', - key: 'persisted_tables', - }) - ).map(transformTableName) ?? []; + +async function getPersistedTables({ strapi }) { + const persistedTables = await strapi.store.get({ + type: 'core', + key: 'persisted_tables', + }); + + return (persistedTables || []).map(transformTableName); +} /** * Add all table names that start with a prefix to the reserved tables in