Create helper function to regenerate rows in tables faster

This commit is contained in:
Nicholas Wallace 2026-05-13 15:34:51 -07:00
parent 38b810bc2e
commit 6a983a53b4
2 changed files with 56 additions and 15 deletions

View file

@ -211,34 +211,56 @@ class Database {
} }
/** /**
* Rebuild all author rows so derived fields stay in sync with the model logic. * Rebuild rows for a model so hooks can recompute derived fields.
*
* @param {import('sequelize').ModelStatic<any>} model
* @param {{
* label?: string,
* pageSize?: number,
* attributes?: string[],
* order?: import('sequelize').Order,
* prepareRow?: (row: any) => void | Promise<void>
* }} [options]
*/ */
async rebuildAuthorRows() { async rebuildComputedTableRows(model, options = {}) {
const pageSize = 500 const { label = model?.name || 'rows', pageSize = 500, attributes = ['id'], order = [['id', 'ASC']], prepareRow = async () => {} } = options
let offset = 0 let offset = 0
let totalChange = 0
while (true) { while (true) {
const authors = await this.authorModel.findAll({ const rows = await model.findAll({
attributes: ['id', 'name', 'libraryId'], attributes,
order: [['id', 'ASC']], order,
limit: pageSize, limit: pageSize,
offset offset
}) })
if (!authors.length) break if (!rows.length) break
for (const authorRef of authors) { for (const row of rows) {
const author = await this.authorModel.findByPk(authorRef.id) await prepareRow(row)
if (!author) continue if (!row.changed()) continue
author.changed('name', true) totalChange++
await author.save({ silent: true }) await row.save({ silent: true })
} }
offset += authors.length offset += rows.length
if (authors.length < pageSize) break if (rows.length < pageSize) break
} }
Logger.debug(`Sanitized ${offset} author rows`) Logger.debug(`${totalChange} out of ${offset} ${label} rows required recalculation of derived columns`)
}
/**
* Rebuild all author rows so derived fields stay in sync with the model logic.
*/
async rebuildAuthorRows() {
await this.rebuildComputedTableRows(this.authorModel, {
label: 'author',
attributes: ['id', 'name', 'lastFirst', 'searchName', 'libraryId'],
prepareRow: (author) => this.authorModel.isDerivedFieldChange(author)
})
} }
/** /**

View file

@ -66,6 +66,25 @@ class Author extends Model {
return this.normalizeSearchName(leftName) === this.normalizeSearchName(rightName) return this.normalizeSearchName(leftName) === this.normalizeSearchName(rightName)
} }
static isDerivedFieldChange(author) {
const derivedFields = this.buildAuthorDerivedFields(author.name)
let changed = false
if (author.lastFirst !== derivedFields.lastFirst) {
author.setDataValue('lastFirst', derivedFields.lastFirst)
author.changed('lastFirst', true)
changed = true
}
if (author.searchName !== derivedFields.searchName) {
author.setDataValue('searchName', derivedFields.searchName)
author.changed('searchName', true)
changed = true
}
return changed
}
/** /**
* Check if author exists * Check if author exists
* @param {string} authorId * @param {string} authorId