diff --git a/src/posts/delete.js b/src/posts/delete.js index 5a2a615e26..8223435c3d 100644 --- a/src/posts/delete.js +++ b/src/posts/delete.js @@ -10,6 +10,7 @@ const notifications = require('../notifications'); const plugins = require('../plugins'); const flags = require('../flags'); const activitypub = require('../activitypub'); +const utils = require('../utils'); module.exports = function (Posts) { Posts.delete = async function (pid, uid) { @@ -108,7 +109,8 @@ module.exports = function (Posts) { }); await db.sortedSetRemoveBulk(bulkRemove); - const incrObjectBulk = [['global', { postCount: -postData.length }]]; + const localCount = postData.filter(p => utils.isNumber(p.pid)).length; + const incrObjectBulk = [['global', { postCount: -localCount }]]; const postsByCategory = _.groupBy(postData, p => parseInt(p.cid, 10)); for (const [cid, posts] of Object.entries(postsByCategory)) { diff --git a/src/topics/create.js b/src/topics/create.js index 8a6c8dafe6..ce21dc4063 100644 --- a/src/topics/create.js +++ b/src/topics/create.js @@ -67,7 +67,7 @@ module.exports = function (Topics) { db.sortedSetsAdd(countedSortedSetKeys, 0, topicData.tid), user.addTopicIdToUser(topicData.uid, topicData.tid, timestamp), db.incrObjectField(`category:${topicData.cid}`, 'topic_count'), - db.incrObjectField('global', 'topicCount'), + utils.isNumber(tid) ? db.incrObjectField('global', 'topicCount') : null, Topics.createTags(data.tags, topicData.tid, timestamp), scheduled ? Promise.resolve() : categories.updateRecentTid(topicData.cid, topicData.tid), ]); diff --git a/src/topics/delete.js b/src/topics/delete.js index 267190b75b..38fe7e0f11 100644 --- a/src/topics/delete.js +++ b/src/topics/delete.js @@ -8,7 +8,7 @@ const categories = require('../categories'); const flags = require('../flags'); const plugins = require('../plugins'); const batch = require('../batch'); - +const utils = require('../utils'); module.exports = function (Topics) { Topics.delete = async function (tid, uid) { @@ -140,7 +140,9 @@ module.exports = function (Topics) { async function reduceCounters(tid) { const incr = -1; - await db.incrObjectFieldBy('global', 'topicCount', incr); + if (utils.isNumber(tid)) { + await db.incrObjectFieldBy('global', 'topicCount', incr); + } const topicData = await Topics.getTopicFields(tid, ['cid', 'postcount']); const postCountChange = incr * topicData.postcount; await Promise.all([ diff --git a/src/upgrades/4.0.0/fix_global_user_and_post_counts.js b/src/upgrades/4.0.0/fix_global_user_and_post_counts.js new file mode 100644 index 0000000000..f8facf9ae6 --- /dev/null +++ b/src/upgrades/4.0.0/fix_global_user_and_post_counts.js @@ -0,0 +1,21 @@ +'use strict'; + +const db = require('../../database'); +const meta = require('../../meta'); + +module.exports = { + name: 'Fix global counts for users and posts due to faulty AP logic', + timestamp: Date.UTC(2024, 5, 25), + method: async () => { + if (!meta.config.activitypubEnabled) { + return; + } + + const counts = await db.sortedSetsCard(['users:joindate', 'posts:pid', 'topics:tid']); + await db.setObject('global', { + userCount: counts[0], + postCount: counts[1], + topicCount: counts[2], + }); + }, +}; diff --git a/src/user/delete.js b/src/user/delete.js index 0dc288447c..c42d00294f 100644 --- a/src/user/delete.js +++ b/src/user/delete.js @@ -142,7 +142,7 @@ module.exports = function (User) { await Promise.all([ db.sortedSetRemoveBulk(bulkRemove), - db.decrObjectField('global', 'userCount'), + utils.isNumber(uid) ? db.decrObjectField('global', 'userCount') : null, db.deleteAll(keys), db.setRemove('invitation:uids', uid), deleteUserIps(uid),