From 5a9eed0a5adfb5cadea0904a51c5bac85fd1db61 Mon Sep 17 00:00:00 2001 From: advplyr Date: Sat, 22 Jul 2023 16:18:55 -0500 Subject: [PATCH] Update:Only load collections when needed --- server/Database.js | 6 -- server/controllers/CollectionController.js | 9 +-- server/controllers/LibraryController.js | 11 ++-- server/controllers/PlaylistController.js | 2 +- server/controllers/RSSFeedController.js | 2 +- server/managers/RssFeedManager.js | 9 +-- server/models/Collection.js | 67 ++++++++++++++++++++++ server/routers/ApiRouter.js | 5 +- 8 files changed, 87 insertions(+), 24 deletions(-) diff --git a/server/Database.js b/server/Database.js index 7e407356..e5f3719e 100644 --- a/server/Database.js +++ b/server/Database.js @@ -19,7 +19,6 @@ class Database { // TODO: below data should be loaded from the DB as needed this.libraryItems = [] this.settings = [] - this.collections = [] this.playlists = [] this.authors = [] this.series = [] @@ -161,9 +160,6 @@ class Database { this.libraryItems = await this.models.libraryItem.loadAllLibraryItems() Logger.info(`[Database] Loaded ${this.libraryItems.length} library items`) - this.collections = await this.models.collection.getOldCollections() - Logger.info(`[Database] Loaded ${this.collections.length} collections`) - this.playlists = await this.models.playlist.getOldPlaylists() Logger.info(`[Database] Loaded ${this.playlists.length} playlists`) @@ -280,7 +276,6 @@ class Database { await this.createBulkCollectionBooks(collectionBooks) } } - this.collections.push(oldCollection) } updateCollection(oldCollection) { @@ -302,7 +297,6 @@ class Database { async removeCollection(collectionId) { if (!this.sequelize) return false await this.models.collection.removeById(collectionId) - this.collections = this.collections.filter(c => c.id !== collectionId) } createCollectionBook(collectionBook) { diff --git a/server/controllers/CollectionController.js b/server/controllers/CollectionController.js index 4665869e..682088cc 100644 --- a/server/controllers/CollectionController.js +++ b/server/controllers/CollectionController.js @@ -20,9 +20,10 @@ class CollectionController { res.json(jsonExpanded) } - findAll(req, res) { + async findAll(req, res) { + const collections = await Database.models.collection.getOldCollections() res.json({ - collections: Database.collections.map(c => c.toJSONExpanded(Database.libraryItems)) + collections: collections.map(c => c.toJSONExpanded(Database.libraryItems)) }) } @@ -160,9 +161,9 @@ class CollectionController { res.json(collection.toJSONExpanded(Database.libraryItems)) } - middleware(req, res, next) { + async middleware(req, res, next) { if (req.params.id) { - const collection = Database.collections.find(c => c.id === req.params.id) + const collection = await Database.models.collection.getById(req.params.id) if (!collection) { return res.status(404).send('Collection not found') } diff --git a/server/controllers/LibraryController.js b/server/controllers/LibraryController.js index bebbac34..807f5a0b 100644 --- a/server/controllers/LibraryController.js +++ b/server/controllers/LibraryController.js @@ -167,10 +167,9 @@ class LibraryController { this.watcher.removeLibrary(library) // Remove collections for library - const collections = Database.collections.filter(c => c.libraryId === library.id) - for (const collection of collections) { - Logger.info(`[Server] deleting collection "${collection.name}" for library "${library.name}"`) - await Database.removeCollection(collection.id) + const numCollectionsRemoved = await Database.models.collection.removeAllForLibrary(library.id) + if (numCollectionsRemoved) { + Logger.info(`[Server] Removed ${numCollectionsRemoved} collections for library "${library.name}"`) } // Remove items in this library @@ -527,7 +526,9 @@ class LibraryController { include: include.join(',') } - let collections = await Promise.all(Database.collections.filter(c => c.libraryId === req.library.id).map(async c => { + const collectionsForLibrary = await Database.models.collection.getAllForLibrary(req.library.id) + + let collections = await Promise.all(collectionsForLibrary.map(async c => { const expanded = c.toJSONExpanded(libraryItems, payload.minified) // If all books restricted to user in this collection then hide this collection diff --git a/server/controllers/PlaylistController.js b/server/controllers/PlaylistController.js index 92eb4f37..d30fdc42 100644 --- a/server/controllers/PlaylistController.js +++ b/server/controllers/PlaylistController.js @@ -200,7 +200,7 @@ class PlaylistController { // POST: api/playlists/collection/:collectionId async createFromCollection(req, res) { - let collection = Database.collections.find(c => c.id === req.params.collectionId) + let collection = await Database.models.collection.getById(req.params.collectionId) if (!collection) { return res.status(404).send('Collection not found') } diff --git a/server/controllers/RSSFeedController.js b/server/controllers/RSSFeedController.js index a6e6abc8..82175e4c 100644 --- a/server/controllers/RSSFeedController.js +++ b/server/controllers/RSSFeedController.js @@ -45,7 +45,7 @@ class RSSFeedController { async openRSSFeedForCollection(req, res) { const options = req.body || {} - const collection = Database.collections.find(li => li.id === req.params.collectionId) + const collection = await Database.models.collection.getById(req.params.collectionId) if (!collection) return res.sendStatus(404) // Check request body options exist diff --git a/server/managers/RssFeedManager.js b/server/managers/RssFeedManager.js index c1c10244..7e4759a2 100644 --- a/server/managers/RssFeedManager.js +++ b/server/managers/RssFeedManager.js @@ -10,9 +10,10 @@ const Feed = require('../objects/Feed') class RssFeedManager { constructor() { } - validateFeedEntity(feedObj) { + async validateFeedEntity(feedObj) { if (feedObj.entityType === 'collection') { - if (!Database.collections.some(li => li.id === feedObj.entityId)) { + const collection = await Database.models.collection.getById(feedObj.entityId) + if (!collection) { Logger.error(`[RssFeedManager] Removing feed "${feedObj.id}". Collection "${feedObj.entityId}" not found`) return false } @@ -42,7 +43,7 @@ class RssFeedManager { const feeds = await Database.models.feed.getOldFeeds() for (const feed of feeds) { // Remove invalid feeds - if (!this.validateFeedEntity(feed)) { + if (!await this.validateFeedEntity(feed)) { await Database.removeFeed(feed.id) } } @@ -101,7 +102,7 @@ class RssFeedManager { await Database.updateFeed(feed) } } else if (feed.entityType === 'collection') { - const collection = Database.collections.find(c => c.id === feed.entityId) + const collection = await Database.models.collection.getById(feed.entityId) if (collection) { const collectionExpanded = collection.toJSONExpanded(Database.libraryItems) diff --git a/server/models/Collection.js b/server/models/Collection.js index 3c4c3a71..3c7c1386 100644 --- a/server/models/Collection.js +++ b/server/models/Collection.js @@ -92,6 +92,73 @@ module.exports = (sequelize) => { } }) } + + /** + * Get collection by id + * @param {string} collectionId + * @returns {Promise} returns null if not found + */ + static async getById(collectionId) { + if (!collectionId) return null + const collection = await this.findByPk(collectionId, { + include: { + model: sequelize.models.book, + include: sequelize.models.libraryItem + }, + order: [[sequelize.models.book, sequelize.models.collectionBook, 'order', 'ASC']] + }) + if (!collection) return null + return this.getOldCollection(collection) + } + + /** + * Remove all collections belonging to library + * @param {string} libraryId + * @returns {Promise} number of collections destroyed + */ + static async removeAllForLibrary(libraryId) { + if (!libraryId) return 0 + return this.destroy({ + where: { + libraryId + } + }) + } + + /** + * Get all collections for a library + * @param {string} libraryId + * @returns {Promise} + */ + static async getAllForLibrary(libraryId) { + if (!libraryId) return [] + const collections = await this.findAll({ + where: { + libraryId + }, + include: { + model: sequelize.models.book, + include: sequelize.models.libraryItem + }, + order: [[sequelize.models.book, sequelize.models.collectionBook, 'order', 'ASC']] + }) + return collections.map(c => this.getOldCollection(c)) + } + + static async getAllForBook(bookId) { + const collections = await this.findAll({ + include: { + model: sequelize.models.book, + where: { + id: bookId + }, + required: true, + include: sequelize.models.libraryItem + }, + order: [[sequelize.models.book, sequelize.models.collectionBook, 'order', 'ASC']] + }) + return collections.map(c => this.getOldCollection(c)) + } } Collection.init({ diff --git a/server/routers/ApiRouter.js b/server/routers/ApiRouter.js index 9db034ff..84fce0e8 100644 --- a/server/routers/ApiRouter.js +++ b/server/routers/ApiRouter.js @@ -392,9 +392,8 @@ class ApiRouter { if (libraryItem.isBook) { // remove book from collections - const collectionsWithBook = Database.collections.filter(c => c.books.includes(libraryItem.id)) - for (let i = 0; i < collectionsWithBook.length; i++) { - const collection = collectionsWithBook[i] + const collectionsWithBook = await Database.models.collection.getAllForBook(libraryItem.media.id) + for (const collection of collectionsWithBook) { collection.removeBook(libraryItem.id) await Database.removeCollectionBook(collection.id, libraryItem.media.id) SocketAuthority.emitter('collection_updated', collection.toJSONExpanded(Database.libraryItems))