fix(federation): avoid duplicate activity delivery (#8429)

* prefer shared inbox over individual inbox

* no new shared inbox for direct recipes

* fix type error
This commit is contained in:
Johann150 2022-04-02 08:16:35 +02:00 committed by GitHub
parent da87171ce7
commit ec9e0db07a

View File

@ -79,37 +79,46 @@ export default class DeliverManager {
const inboxes = new Set<string>();
// build inbox list
for (const recipe of this.recipes) {
if (isFollowers(recipe)) {
// followers deliver
// TODO: SELECT DISTINCT ON ("followerSharedInbox") "followerSharedInbox" みたいな問い合わせにすればよりパフォーマンス向上できそう
// ただ、sharedInboxがnullなリモートユーザーも稀におり、その対応ができなさそう
const followers = await Followings.find({
where: {
followeeId: this.actor.id,
followerHost: Not(IsNull()),
},
select: {
followerSharedInbox: true,
followerInbox: true,
},
}) as {
followerSharedInbox: string | null;
followerInbox: string;
}[];
/*
build inbox list
for (const following of followers) {
const inbox = following.followerSharedInbox || following.followerInbox;
inboxes.add(inbox);
}
} else if (isDirect(recipe)) {
// direct deliver
const inbox = recipe.to.inbox;
if (inbox) inboxes.add(inbox);
Process follower recipes first to avoid duplication when processing
direct recipes later.
*/
if (this.recipes.some(r => isFollowers(r)) {
// followers deliver
// TODO: SELECT DISTINCT ON ("followerSharedInbox") "followerSharedInbox" みたいな問い合わせにすればよりパフォーマンス向上できそう
// ただ、sharedInboxがnullなリモートユーザーも稀におり、その対応ができなさそう
const followers = await Followings.find({
where: {
followeeId: this.actor.id,
followerHost: Not(IsNull()),
},
select: {
followerSharedInbox: true,
followerInbox: true,
},
}) as {
followerSharedInbox: string | null;
followerInbox: string;
}[];
for (const following of followers) {
const inbox = following.followerSharedInbox || following.followerInbox;
inboxes.add(inbox);
}
}
this.recipes.filter((recipe): recipe is IDirectRecipe => {
// followers recipes have already been processed
isDirect(recipe)
// check that shared inbox has not been added yet
&& !(recipe.to.sharedInbox && inboxes.has(recipe.to.sharedInbox))
// check that they actually have an inbox
&& recipe.to.inbox
})
.forEach(recipe => inboxes.add(recipe.to.inbox));
// deliver
for (const inbox of inboxes) {
deliver(this.actor, this.activity, inbox);