fix: use ftt for outbox (#15819)

* fix: use ftt for outbox

* chore: check for enableFanoutTimeline

* lint: fix lint
This commit is contained in:
anatawa12 2025-04-15 16:15:27 +09:00 committed by GitHub
parent f454e820bd
commit b2e3e65896
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 39 additions and 11 deletions

View File

@ -54,7 +54,7 @@ export class FanoutTimelineEndpointService {
} }
@bindThis @bindThis
private async getMiNotes(ps: TimelineOptions): Promise<MiNote[]> { async getMiNotes(ps: TimelineOptions): Promise<MiNote[]> {
// 呼び出し元と以下の処理をシンプルにするためにdbFallbackを置き換える // 呼び出し元と以下の処理をシンプルにするためにdbFallbackを置き換える
if (!ps.useDbFallback) ps.dbFallback = () => Promise.resolve([]); if (!ps.useDbFallback) ps.dbFallback = () => Promise.resolve([]);

View File

@ -32,6 +32,7 @@ import { isQuote, isRenote } from '@/misc/is-renote.js';
import * as Acct from '@/misc/acct.js'; import * as Acct from '@/misc/acct.js';
import type { FastifyInstance, FastifyRequest, FastifyReply, FastifyPluginOptions, FastifyBodyParser } from 'fastify'; import type { FastifyInstance, FastifyRequest, FastifyReply, FastifyPluginOptions, FastifyBodyParser } from 'fastify';
import type { FindOptionsWhere } from 'typeorm'; import type { FindOptionsWhere } from 'typeorm';
import { FanoutTimelineEndpointService } from '@/core/FanoutTimelineEndpointService.js';
const ACTIVITY_JSON = 'application/activity+json; charset=utf-8'; const ACTIVITY_JSON = 'application/activity+json; charset=utf-8';
const LD_JSON = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"; charset=utf-8'; const LD_JSON = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"; charset=utf-8';
@ -75,6 +76,7 @@ export class ActivityPubServerService {
private queueService: QueueService, private queueService: QueueService,
private userKeypairService: UserKeypairService, private userKeypairService: UserKeypairService,
private queryService: QueryService, private queryService: QueryService,
private fanoutTimelineEndpointService: FanoutTimelineEndpointService,
) { ) {
//this.createServer = this.createServer.bind(this); //this.createServer = this.createServer.bind(this);
} }
@ -461,16 +463,28 @@ export class ActivityPubServerService {
const partOf = `${this.config.url}/users/${userId}/outbox`; const partOf = `${this.config.url}/users/${userId}/outbox`;
if (page) { if (page) {
const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), sinceId, untilId) const notes = this.meta.enableFanoutTimeline ? await this.fanoutTimelineEndpointService.getMiNotes({
.andWhere('note.userId = :userId', { userId: user.id }) sinceId: sinceId ?? null,
.andWhere(new Brackets(qb => { untilId: untilId ?? null,
qb limit: limit,
.where('note.visibility = \'public\'') allowPartial: false, // Possibly true? IDK it's OK for ordered collection.
.orWhere('note.visibility = \'home\''); me: null,
})) redisTimelines: [
.andWhere('note.localOnly = FALSE'); `userTimeline:${user.id}`,
`userTimelineWithReplies:${user.id}`,
const notes = await query.limit(limit).getMany(); ],
useDbFallback: true,
ignoreAuthorFromMute: true,
excludePureRenotes: false,
noteFilter: (note) => {
if (note.visibility !== 'home' && note.visibility !== 'public') return false;
if (note.localOnly) return false;
return true;
},
dbFallback: async (untilId, sinceId, limit) => {
return await this.getUserNotesFromDb(sinceId, untilId, limit, user.id);
},
}) : await this.getUserNotesFromDb(sinceId ?? null, untilId ?? null, limit, user.id);
if (sinceId) notes.reverse(); if (sinceId) notes.reverse();
@ -508,6 +522,20 @@ export class ActivityPubServerService {
} }
} }
@bindThis
private async getUserNotesFromDb(untilId: string | null, sinceId: string | null, limit: number, userId: MiUser['id']) {
return await this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), sinceId, untilId)
.andWhere('note.userId = :userId', { userId })
.andWhere(new Brackets(qb => {
qb
.where('note.visibility = \'public\'')
.orWhere('note.visibility = \'home\'');
}))
.andWhere('note.localOnly = FALSE')
.limit(limit)
.getMany();
}
@bindThis @bindThis
private async userInfo(request: FastifyRequest, reply: FastifyReply, user: MiUser | null) { private async userInfo(request: FastifyRequest, reply: FastifyReply, user: MiUser | null) {
if (this.meta.federation === 'none') { if (this.meta.federation === 'none') {