mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-05-18 09:21:31 +00:00
Merge 3a751f711a into 47ea6b5092
This commit is contained in:
commit
d5c4c0f800
9 changed files with 221 additions and 106 deletions
|
|
@ -35,6 +35,7 @@ const MiscController = require('../controllers/MiscController')
|
|||
const ShareController = require('../controllers/ShareController')
|
||||
const StatsController = require('../controllers/StatsController')
|
||||
const ApiKeyController = require('../controllers/ApiKeyController')
|
||||
const { checkRemoveEmptySeries, checkRemoveAuthorsWithNoBooks } = require('../utils/cleanup')
|
||||
|
||||
class ApiRouter {
|
||||
constructor(Server) {
|
||||
|
|
@ -407,54 +408,7 @@ class ApiRouter {
|
|||
* @param {string[]} seriesIds
|
||||
*/
|
||||
async checkRemoveEmptySeries(seriesIds) {
|
||||
if (!seriesIds?.length) return
|
||||
|
||||
const transaction = await Database.sequelize.transaction()
|
||||
try {
|
||||
const seriesToRemove = (
|
||||
await Database.seriesModel.findAll({
|
||||
where: [
|
||||
{
|
||||
id: seriesIds
|
||||
},
|
||||
sequelize.where(sequelize.literal('(SELECT count(*) FROM bookSeries bs WHERE bs.seriesId = series.id)'), 0)
|
||||
],
|
||||
attributes: ['id', 'name', 'libraryId'],
|
||||
include: {
|
||||
model: Database.bookModel,
|
||||
attributes: ['id'],
|
||||
required: false // Ensure it includes series even if no books exist
|
||||
},
|
||||
transaction
|
||||
})
|
||||
).map((s) => ({ id: s.id, name: s.name, libraryId: s.libraryId }))
|
||||
|
||||
if (seriesToRemove.length) {
|
||||
await Database.seriesModel.destroy({
|
||||
where: {
|
||||
id: seriesToRemove.map((s) => s.id)
|
||||
},
|
||||
transaction
|
||||
})
|
||||
}
|
||||
|
||||
await transaction.commit()
|
||||
|
||||
seriesToRemove.forEach(({ id, name, libraryId }) => {
|
||||
Logger.info(`[ApiRouter] Series "${name}" is now empty. Removing series`)
|
||||
|
||||
// Remove series from library filter data
|
||||
Database.removeSeriesFromFilterData(libraryId, id)
|
||||
SocketAuthority.emitter('series_removed', { id: id, libraryId: libraryId })
|
||||
})
|
||||
// Close rss feeds - remove from db and emit socket event
|
||||
if (seriesToRemove.length) {
|
||||
await RssFeedManager.closeFeedsForEntityIds(seriesToRemove.map((s) => s.id))
|
||||
}
|
||||
} catch (error) {
|
||||
await transaction.rollback()
|
||||
Logger.error(`[ApiRouter] Error removing empty series: ${error.message}`)
|
||||
}
|
||||
return checkRemoveEmptySeries(seriesIds)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -465,56 +419,7 @@ class ApiRouter {
|
|||
* @returns {Promise<void>}
|
||||
*/
|
||||
async checkRemoveAuthorsWithNoBooks(authorIds) {
|
||||
if (!authorIds?.length) return
|
||||
|
||||
const transaction = await Database.sequelize.transaction()
|
||||
try {
|
||||
// Select authors with locking to prevent concurrent updates
|
||||
const bookAuthorsToRemove = (
|
||||
await Database.authorModel.findAll({
|
||||
where: [
|
||||
{
|
||||
id: authorIds,
|
||||
asin: {
|
||||
[sequelize.Op.or]: [null, '']
|
||||
},
|
||||
description: {
|
||||
[sequelize.Op.or]: [null, '']
|
||||
},
|
||||
imagePath: {
|
||||
[sequelize.Op.or]: [null, '']
|
||||
}
|
||||
},
|
||||
sequelize.where(sequelize.literal('(SELECT count(*) FROM bookAuthors ba WHERE ba.authorId = author.id)'), 0)
|
||||
],
|
||||
attributes: ['id', 'name', 'libraryId'],
|
||||
raw: true,
|
||||
transaction
|
||||
})
|
||||
).map((au) => ({ id: au.id, name: au.name, libraryId: au.libraryId }))
|
||||
|
||||
if (bookAuthorsToRemove.length) {
|
||||
await Database.authorModel.destroy({
|
||||
where: {
|
||||
id: bookAuthorsToRemove.map((au) => au.id)
|
||||
},
|
||||
transaction
|
||||
})
|
||||
}
|
||||
|
||||
await transaction.commit()
|
||||
|
||||
// Remove all book authors after completing remove from database
|
||||
bookAuthorsToRemove.forEach(({ id, name, libraryId }) => {
|
||||
Database.removeAuthorFromFilterData(libraryId, id)
|
||||
// TODO: Clients were expecting full author in payload but its unnecessary
|
||||
SocketAuthority.emitter('author_removed', { id, libraryId })
|
||||
Logger.info(`[ApiRouter] Removed author "${name}" with no books`)
|
||||
})
|
||||
} catch (error) {
|
||||
await transaction.rollback()
|
||||
Logger.error(`[ApiRouter] Error removing authors: ${error.message}`)
|
||||
}
|
||||
return checkRemoveAuthorsWithNoBooks(authorIds)
|
||||
}
|
||||
|
||||
async getUserListeningSessionsHelper(userId) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue