From 7eebcbdbbc0b58a36f49d61486029465fb499788 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Sun, 7 Feb 2021 19:13:21 -0500 Subject: [PATCH] perf: only load thumbs for topics that actually have thumbs --- src/topics/index.js | 6 ++--- src/topics/thumbs.js | 23 +++++++++++++++---- src/upgrades/1.17.0/topic_thumb_count.js | 29 ++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 7 deletions(-) create mode 100644 src/upgrades/1.17.0/topic_thumb_count.js diff --git a/src/topics/index.js b/src/topics/index.js index edb528c96e..7b6bef2017 100644 --- a/src/topics/index.js +++ b/src/topics/index.js @@ -82,7 +82,7 @@ Topics.getTopicsByTids = async function (tids, options) { user.getMultipleUserSettings(uids), categories.getCategoriesFields(cids, ['cid', 'name', 'slug', 'icon', 'backgroundImage', 'imageClass', 'bgColor', 'color', 'disabled']), loadGuestHandles(), - Topics.thumbs.get(tids), + Topics.thumbs.load(topics), ]); users.forEach((userObj, idx) => { @@ -167,11 +167,11 @@ Topics.getTopicWithPosts = async function (topicData, set, uid, start, stop, rev getDeleter(topicData), getMerger(topicData), getRelated(topicData, uid), - Topics.thumbs.get(topicData.tid), + Topics.thumbs.load([topicData]), Topics.events.get(topicData.tid), ]); - topicData.thumbs = thumbs; + topicData.thumbs = thumbs[0]; topicData.posts = posts; topicData.events = events; topicData.category = category; diff --git a/src/topics/thumbs.js b/src/topics/thumbs.js index 0eab34faa4..6c86505ecd 100644 --- a/src/topics/thumbs.js +++ b/src/topics/thumbs.js @@ -1,6 +1,7 @@ 'use strict'; +const _ = require('lodash'); const nconf = require('nconf'); const path = require('path'); const validator = require('validator'); @@ -19,6 +20,14 @@ Thumbs.exists = async function (tid, path) { return db.isSortedSetMember(`topic:${tid}:thumbs`, path); }; +Thumbs.load = async function (topicData) { + const topicsWithThumbs = topicData.filter(t => parseInt(t.numThumbs, 10) > 0); + const tidsWithThumbs = topicsWithThumbs.map(t => t.tid); + const thumbs = await Thumbs.get(tidsWithThumbs); + const tidToThumbs = _.zipObject(tidsWithThumbs, thumbs); + return topicData.map(t => tidToThumbs[t.tid] || []); +}; + Thumbs.get = async function (tids) { // Allow singular or plural usage let singular = false; @@ -27,14 +36,14 @@ Thumbs.get = async function (tids) { singular = true; } - if (!meta.config.allowTopicsThumbnail) { + if (!meta.config.allowTopicsThumbnail || !tids.length) { return singular ? [] : tids.map(() => []); } const hasTimestampPrefix = /^\d+-/; const upload_url = nconf.get('relative_path') + nconf.get('upload_url'); const sets = tids.map(tid => `${validator.isUUID(String(tid)) ? 'draft' : 'topic'}:${tid}:thumbs`); - const thumbs = await Promise.all(sets.map(set => getThumbs(set))); + const thumbs = await Promise.all(sets.map(getThumbs)); let response = thumbs.map((thumbSet, idx) => thumbSet.map(thumb => ({ id: tids[idx], name: (() => { @@ -69,13 +78,15 @@ Thumbs.associate = async function ({ id, path: relativePath, url }) { if (relativePath) { value = value.replace(nconf.get('upload_path'), ''); } - + const topics = require('.'); await db.sortedSetAdd(set, numThumbs, value); + if (!isDraft) { + await topics.setTopicField(id, 'numThumbs', numThumbs); + } cache.del(set); // Associate thumbnails with the main pid (only on local upload) if (!isDraft && relativePath) { - const topics = require('.'); const mainPid = (await topics.getMainPids([id]))[0]; posts.uploads.associate(mainPid, relativePath.replace('/files/', '')); } @@ -110,6 +121,10 @@ Thumbs.delete = async function (id, relativePath) { // Dissociate thumbnails with the main pid if (!isDraft) { const topics = require('.'); + const numThumbs = await db.sortedSetCard(set); + if (!numThumbs) { + await db.deleteObjectField('topic:' + id, 'numThumbs'); + } const mainPid = (await topics.getMainPids([id]))[0]; posts.uploads.dissociate(mainPid, relativePath.replace('/files/', '')); } diff --git a/src/upgrades/1.17.0/topic_thumb_count.js b/src/upgrades/1.17.0/topic_thumb_count.js new file mode 100644 index 0000000000..f6c5242ff8 --- /dev/null +++ b/src/upgrades/1.17.0/topic_thumb_count.js @@ -0,0 +1,29 @@ +'use strict'; + +const _ = require('lodash'); +const db = require('../../database'); +const batch = require('../../batch'); + +module.exports = { + name: 'Store number of thumbs a topic has in the topic object', + timestamp: Date.UTC(2021, 1, 7), + method: async function () { + const progress = this.progress; + + await batch.processSortedSet('topics:tid', async function (tids) { + const keys = tids.map(tid => 'topic:' + tid + ':thumbs'); + const counts = await db.sortedSetsCard(keys); + const tidToCount = _.zip(tids, counts); + const tidsWithThumbs = tids.filter((t, i) => counts[i] > 0); + await db.setObjectBulk( + tidsWithThumbs.map(tid => 'topic:' + tid), + tidsWithThumbs.map(tid => ({ numThumbs: tidToCount[tid] })) + ); + + progress.incr(tids.length); + }, { + batch: 500, + progress: progress, + }); + }, +};