mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-10-30 02:25:55 +01:00
* fix: #8954, clear purged replies and toPids * fix: redis test
This commit is contained in:
committed by
GitHub
parent
39dae0aaff
commit
5bb5ec4618
@@ -149,7 +149,7 @@ module.exports = function (module) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
module.deleteObjectFields = async function (key, fields) {
|
module.deleteObjectFields = async function (key, fields) {
|
||||||
if (!key || !Array.isArray(fields) || !fields.length) {
|
if (!key || (Array.isArray(key) && !key.length) || !Array.isArray(fields) || !fields.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fields = fields.filter(Boolean);
|
fields = fields.filter(Boolean);
|
||||||
@@ -162,8 +162,12 @@ module.exports = function (module) {
|
|||||||
field = helpers.fieldToString(field);
|
field = helpers.fieldToString(field);
|
||||||
data[field] = '';
|
data[field] = '';
|
||||||
});
|
});
|
||||||
|
if (Array.isArray(key)) {
|
||||||
|
await module.client.collection('objects').updateMany({ _key: { $in: key } }, { $unset: data });
|
||||||
|
} else {
|
||||||
await module.client.collection('objects').updateOne({ _key: key }, { $unset: data });
|
await module.client.collection('objects').updateOne({ _key: key }, { $unset: data });
|
||||||
|
}
|
||||||
|
|
||||||
cache.del(key);
|
cache.del(key);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -247,10 +247,10 @@ SELECT (h."data" ? $2::TEXT AND h."data"->>$2::TEXT IS NOT NULL) b
|
|||||||
};
|
};
|
||||||
|
|
||||||
module.deleteObjectFields = async function (key, fields) {
|
module.deleteObjectFields = async function (key, fields) {
|
||||||
if (!key || !Array.isArray(fields) || !fields.length) {
|
if (!key || (Array.isArray(key) && !key.length) || !Array.isArray(fields) || !fields.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
async function delKey(key, fields) {
|
||||||
await module.pool.query({
|
await module.pool.query({
|
||||||
name: 'deleteObjectFields',
|
name: 'deleteObjectFields',
|
||||||
text: `
|
text: `
|
||||||
@@ -261,6 +261,12 @@ UPDATE "legacy_hash"
|
|||||||
WHERE "_key" = $1::TEXT`,
|
WHERE "_key" = $1::TEXT`,
|
||||||
values: [key, fields],
|
values: [key, fields],
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
if (Array.isArray(key)) {
|
||||||
|
await Promise.all(key.map(k => delKey(k, fields)));
|
||||||
|
} else {
|
||||||
|
await delKey(key, fields);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
module.incrObjectField = async function (key, field) {
|
module.incrObjectField = async function (key, field) {
|
||||||
|
|||||||
@@ -150,14 +150,21 @@ module.exports = function (module) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
module.deleteObjectFields = async function (key, fields) {
|
module.deleteObjectFields = async function (key, fields) {
|
||||||
if (!key || !Array.isArray(fields) || !fields.length) {
|
if (!key || (Array.isArray(key) && !key.length) || !Array.isArray(fields) || !fields.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fields = fields.filter(Boolean);
|
fields = fields.filter(Boolean);
|
||||||
if (!fields.length) {
|
if (!fields.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (Array.isArray(key)) {
|
||||||
|
const batch = module.client.batch();
|
||||||
|
key.forEach(k => batch.hdel(k, fields));
|
||||||
|
await helpers.execBatch(batch);
|
||||||
|
} else {
|
||||||
await module.client.async.hdel(key, fields);
|
await module.client.async.hdel(key, fields);
|
||||||
|
}
|
||||||
|
|
||||||
cache.del(key);
|
cache.del(key);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -122,13 +122,18 @@ module.exports = function (Posts) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function deletePostFromReplies(postData) {
|
async function deletePostFromReplies(postData) {
|
||||||
if (!parseInt(postData.toPid, 10)) {
|
const replyPids = await db.getSortedSetMembers('pid:' + postData.pid + ':replies');
|
||||||
return;
|
const promises = [
|
||||||
|
db.deleteObjectFields(
|
||||||
|
replyPids.map(pid => 'post:' + pid), ['toPid']
|
||||||
|
),
|
||||||
|
db.delete('pid:' + postData.pid + ':replies'),
|
||||||
|
];
|
||||||
|
if (parseInt(postData.toPid, 10)) {
|
||||||
|
promises.push(db.sortedSetRemove('pid:' + postData.toPid + ':replies', postData.pid));
|
||||||
|
promises.push(db.decrObjectField('post:' + postData.toPid, 'replies'));
|
||||||
}
|
}
|
||||||
await Promise.all([
|
await Promise.all(promises);
|
||||||
db.sortedSetRemove('pid:' + postData.toPid + ':replies', postData.pid),
|
|
||||||
db.decrObjectField('post:' + postData.toPid, 'replies'),
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function deletePostFromGroups(postData) {
|
async function deletePostFromGroups(postData) {
|
||||||
|
|||||||
33
src/upgrades/1.15.4/clear_purged_replies.js
Normal file
33
src/upgrades/1.15.4/clear_purged_replies.js
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const _ = require('lodash');
|
||||||
|
const db = require('../../database');
|
||||||
|
|
||||||
|
const batch = require('../../batch');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name: 'Clear purged replies and toPid',
|
||||||
|
timestamp: Date.UTC(2020, 10, 26),
|
||||||
|
method: async function () {
|
||||||
|
const progress = this.progress;
|
||||||
|
|
||||||
|
await batch.processSortedSet('posts:pid', async function (pids) {
|
||||||
|
progress.incr(pids.length);
|
||||||
|
let postData = await db.getObjects(pids.map(pid => 'post:' + pid));
|
||||||
|
postData = postData.filter(p => p && parseInt(p.toPid, 10));
|
||||||
|
if (!postData.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const toPids = postData.map(p => p.toPid);
|
||||||
|
const exists = await db.exists(toPids.map(pid => 'post:' + pid));
|
||||||
|
const pidsToDelete = postData.filter((p, index) => !exists[index]).map(p => p.pid);
|
||||||
|
await db.deleteObjectFields(pidsToDelete.map(pid => 'post:' + pid), ['toPid']);
|
||||||
|
|
||||||
|
const repliesToDelete = _.uniq(toPids.filter((pid, index) => !exists[index]));
|
||||||
|
await db.deleteAll(repliesToDelete.map(pid => 'pid:' + pid + ':replies'));
|
||||||
|
}, {
|
||||||
|
progress: progress,
|
||||||
|
batchSize: 500,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -415,6 +415,16 @@ describe('Hash methods', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should delete multiple fields of multiple objects', async function () {
|
||||||
|
await db.setObject('deleteFields1', { foo: 'foo1', baz: '2' });
|
||||||
|
await db.setObject('deleteFields2', { foo: 'foo2', baz: '3' });
|
||||||
|
await db.deleteObjectFields(['deleteFields1', 'deleteFields2'], ['baz']);
|
||||||
|
const obj1 = await db.getObject('deleteFields1');
|
||||||
|
const obj2 = await db.getObject('deleteFields2');
|
||||||
|
assert.deepStrictEqual(obj1, { foo: 'foo1' });
|
||||||
|
assert.deepStrictEqual(obj2, { foo: 'foo2' });
|
||||||
|
});
|
||||||
|
|
||||||
it('should not error if fields is empty array', async () => {
|
it('should not error if fields is empty array', async () => {
|
||||||
await db.deleteObjectFields('someKey', []);
|
await db.deleteObjectFields('someKey', []);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -190,6 +190,22 @@ describe('Topic\'s', function () {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should delete nested relies properly', async function () {
|
||||||
|
const result = await topics.post({ uid: fooUid, title: 'nested test', content: 'main post', cid: topic.categoryId });
|
||||||
|
const reply1 = await topics.reply({ uid: fooUid, content: 'reply post 1', tid: result.topicData.tid });
|
||||||
|
const reply2 = await topics.reply({ uid: fooUid, content: 'reply post 2', tid: result.topicData.tid, toPid: reply1.pid });
|
||||||
|
let replies = await socketPosts.getReplies({ uid: fooUid }, reply1.pid);
|
||||||
|
assert.strictEqual(replies.length, 1);
|
||||||
|
assert.strictEqual(replies[0].content, 'reply post 2');
|
||||||
|
let toPid = await posts.getPostField(reply2.pid, 'toPid');
|
||||||
|
assert.strictEqual(parseInt(toPid, 10), parseInt(reply1.pid, 10));
|
||||||
|
await posts.purge(reply1.pid, fooUid);
|
||||||
|
replies = await socketPosts.getReplies({ uid: fooUid }, reply1.pid);
|
||||||
|
assert.strictEqual(replies.length, 0);
|
||||||
|
toPid = await posts.getPostField(reply2.pid, 'toPid');
|
||||||
|
assert.strictEqual(toPid, null);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Get methods', function () {
|
describe('Get methods', function () {
|
||||||
|
|||||||
Reference in New Issue
Block a user