refactor: post announce logic to save to separate zset instead of to topic events, closes #12536

This commit is contained in:
Julian Lam
2024-05-01 14:44:29 -04:00
parent 5e2031977a
commit 119800d936
4 changed files with 100 additions and 28 deletions

View File

@@ -173,23 +173,7 @@ inbox.announce = async (req) => {
winston.info(`[activitypub/inbox/announce] Parsing id ${pid}`); winston.info(`[activitypub/inbox/announce] Parsing id ${pid}`);
if (!cid) { // Topic events from actors followed by users only if (!cid) { // Topic events from actors followed by users only
// No double-announce allowed await activitypub.notes.announce.add(pid, actor, timestamp);
const existing = await topics.events.find(tid, {
type: 'announce',
uid: actor,
pid,
});
if (existing.length) {
await topics.events.purge(tid, existing);
}
await topics.events.log(tid, {
type: 'announce',
uid: actor,
href: `/post/${encodeURIComponent(pid)}`,
pid,
timestamp,
});
} }
}; };
@@ -389,17 +373,7 @@ inbox.undo = async (req) => {
winston.verbose(`[activitypub/inbox/undo] Attempted to undo announce of ${id} but couldn't find it, so doing nothing.`); winston.verbose(`[activitypub/inbox/undo] Attempted to undo announce of ${id} but couldn't find it, so doing nothing.`);
} }
const tid = await posts.getPostField(id, 'tid'); await activitypub.notes.announce.remove(id, actor);
const existing = await topics.events.find(tid, {
type: 'announce',
uid: actor,
pid: id,
});
if (existing.length) {
await topics.events.purge(tid, existing);
}
notifications.rescind(`announce:post:${id}:uid:${actor}`); notifications.rescind(`announce:post:${id}:uid:${actor}`);
break; break;
} }

View File

@@ -304,3 +304,49 @@ Notes.getCategoryFollowers = async (cid) => {
return uids; return uids;
}; };
Notes.announce = {};
Notes.announce.list = async ({ pid, tid }) => {
let pids = [];
if (pid) {
pids = [pid];
} else if (tid) {
let mainPid;
([pids, mainPid] = await Promise.all([
db.getSortedSetMembers(`tid:${tid}:posts`),
topics.getTopicField(tid, 'mainPid'),
]));
pids.unshift(mainPid);
}
if (!pids.length) {
return [];
}
const keys = pids.map(pid => `pid:${pid}:announces`);
let announces = await db.getSortedSetsMembersWithScores(keys);
announces = announces.reduce((memo, cur, idx) => {
if (cur.length) {
const pid = pids[idx];
cur.forEach(({ value: actor, score: timestamp }) => {
memo.push({ pid, actor, timestamp });
});
}
return memo;
}, []);
return announces;
};
Notes.announce.add = async (pid, actor, timestamp = Date.now()) => {
await db.sortedSetAdd(`pid:${pid}:announces`, timestamp, actor);
};
Notes.announce.remove = async (pid, actor) => {
await db.sortedSetRemove(`pid:${pid}:announces`, actor);
};
Notes.announce.removeAll = async (pid) => {
await db.delete(`pid:${pid}:announces`);
};

View File

@@ -10,6 +10,7 @@ const categories = require('../categories');
const plugins = require('../plugins'); const plugins = require('../plugins');
const translator = require('../translator'); const translator = require('../translator');
const privileges = require('../privileges'); const privileges = require('../privileges');
const activitypub = require('../activitypub');
const utils = require('../utils'); const utils = require('../utils');
const helpers = require('../helpers'); const helpers = require('../helpers');
@@ -176,6 +177,19 @@ async function modifyEvent({ tid, uid, eventIds, timestamps, events }) {
}); });
} }
// Add post announces
const announces = await activitypub.notes.announce.list({ tid });
announces.forEach(({ actor, pid, timestamp }) => {
events.push({
type: 'announce',
uid: actor,
href: `/post/${encodeURIComponent(pid)}`,
pid,
timestamp,
});
timestamps.push(timestamp);
});
const [users, fromCategories, userSettings] = await Promise.all([ const [users, fromCategories, userSettings] = await Promise.all([
getUserInfo(events.map(event => event.uid).filter(Boolean)), getUserInfo(events.map(event => event.uid).filter(Boolean)),
getCategoryInfo(events.map(event => event.fromCid).filter(Boolean)), getCategoryInfo(events.map(event => event.fromCid).filter(Boolean)),

View File

@@ -0,0 +1,38 @@
'use strict';
const db = require('../../database');
const batch = require('../../batch');
const topics = require('../../topics');
module.exports = {
name: 'Save ActivityPub Announces in their own per-post sorted set',
timestamp: Date.UTC(2024, 4, 1),
method: async function () {
const { progress } = this;
const bulkOp = [];
await batch.processSortedSet('topics:tid', async (tids, next) => {
await Promise.all(tids.map(async (tid) => {
const announces = await topics.events.find(tid, {
type: 'announce',
});
if (announces.length) {
await Promise.all(announces.map(async (eid) => {
const event = await db.getObject(`topicEvent:${eid}`);
if (['uid', 'pid', 'timestamp'].every(prop => event.hasOwnProperty(prop))) {
bulkOp.push([`pid:${event.pid}:announces`, event.timestamp, event.uid]);
}
}));
console.log('piurging', tid);
await topics.events.purge(tid, announces);
}
}));
progress.incr(tids.length);
}, { progress });
await db.sortedSetAddBulk(bulkOp);
},
};