chore(endpoints/channels/timeline): FanoutTimelineEndpointServiceで再実装

This commit is contained in:
anatawa12 2023-11-28 23:06:21 +09:00
parent f0e41d7c24
commit 9bd88f1ef6
No known key found for this signature in database
GPG Key ID: 9CA909848B8E4EA6
1 changed files with 49 additions and 60 deletions

View File

@ -12,10 +12,11 @@ import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
import ActiveUsersChart from '@/core/chart/charts/active-users.js'; import ActiveUsersChart from '@/core/chart/charts/active-users.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { IdService } from '@/core/IdService.js'; import { IdService } from '@/core/IdService.js';
import { FanoutTimelineService } from '@/core/FanoutTimelineService.js';
import { isUserRelated } from '@/misc/is-user-related.js'; import { isUserRelated } from '@/misc/is-user-related.js';
import { CacheService } from '@/core/CacheService.js'; import { CacheService } from '@/core/CacheService.js';
import { MetaService } from '@/core/MetaService.js'; import { MetaService } from '@/core/MetaService.js';
import { FanoutTimelineEndpointService } from '@/core/FanoutTimelineEndpointService.js';
import { MiLocalUser } from '@/models/User.js';
import { ApiError } from '../../error.js'; import { ApiError } from '../../error.js';
export const meta = { export const meta = {
@ -58,9 +59,6 @@ export const paramDef = {
@Injectable() @Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
constructor( constructor(
@Inject(DI.redisForTimelines)
private redisForTimelines: Redis.Redis,
@Inject(DI.notesRepository) @Inject(DI.notesRepository)
private notesRepository: NotesRepository, private notesRepository: NotesRepository,
@ -70,7 +68,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private idService: IdService, private idService: IdService,
private noteEntityService: NoteEntityService, private noteEntityService: NoteEntityService,
private queryService: QueryService, private queryService: QueryService,
private fanoutTimelineService: FanoutTimelineService, private fanoutTimelineEndpointService: FanoutTimelineEndpointService,
private cacheService: CacheService, private cacheService: CacheService,
private activeUsersChart: ActiveUsersChart, private activeUsersChart: ActiveUsersChart,
private metaService: MetaService, private metaService: MetaService,
@ -78,7 +76,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
super(meta, paramDef, async (ps, me) => { super(meta, paramDef, async (ps, me) => {
const untilId = ps.untilId ?? (ps.untilDate ? this.idService.gen(ps.untilDate!) : null); const untilId = ps.untilId ?? (ps.untilDate ? this.idService.gen(ps.untilDate!) : null);
const sinceId = ps.sinceId ?? (ps.sinceDate ? this.idService.gen(ps.sinceDate!) : null); const sinceId = ps.sinceId ?? (ps.sinceDate ? this.idService.gen(ps.sinceDate!) : null);
const isRangeSpecified = untilId != null && sinceId != null;
const serverSettings = await this.metaService.fetch(); const serverSettings = await this.metaService.fetch();
@ -92,47 +89,43 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
if (me) this.activeUsersChart.read(me); if (me) this.activeUsersChart.read(me);
if (serverSettings.enableFanoutTimeline && (isRangeSpecified || sinceId == null)) { if (!serverSettings.enableFanoutTimeline) {
return await this.noteEntityService.packMany(await this.getFromDb({ untilId, sinceId, limit: ps.limit, channelId: channel.id }, me), me);
}
const [ const [
userIdsWhoMeMuting, userIdsWhoMeMuting,
] = me ? await Promise.all([ ] = me ? await Promise.all([
this.cacheService.userMutingsCache.fetch(me.id), this.cacheService.userMutingsCache.fetch(me.id),
]) : [new Set<string>()]; ]) : [new Set<string>()];
let noteIds = await this.fanoutTimelineService.get(`channelTimeline:${channel.id}`, untilId, sinceId); return await this.fanoutTimelineEndpointService.timeline({
noteIds = noteIds.slice(0, ps.limit); untilId,
sinceId,
if (noteIds.length > 0) { limit: ps.limit,
const query = this.notesRepository.createQueryBuilder('note') me,
.where('note.id IN (:...noteIds)', { noteIds: noteIds }) redisTimelines: [`channelTimeline:${channel.id}`],
.innerJoinAndSelect('note.user', 'user') noteFilter: note => {
.leftJoinAndSelect('note.reply', 'reply')
.leftJoinAndSelect('note.renote', 'renote')
.leftJoinAndSelect('reply.user', 'replyUser')
.leftJoinAndSelect('renote.user', 'renoteUser')
.leftJoinAndSelect('note.channel', 'channel');
let timeline = await query.getMany();
timeline = timeline.filter(note => {
if (me && isUserRelated(note, userIdsWhoMeMuting)) return false; if (me && isUserRelated(note, userIdsWhoMeMuting)) return false;
return true; return true;
},
dbFallback: async (untilId, sinceId, limit) => {
return await this.getFromDb({ untilId, sinceId, limit, channelId: channel.id }, me);
},
});
}); });
// TODO: フィルタで件数が減った場合の埋め合わせ処理
timeline.sort((a, b) => a.id > b.id ? -1 : 1);
if (timeline.length > 0) {
return await this.noteEntityService.packMany(timeline, me);
}
}
} }
private async getFromDb(ps: {
untilId: string | null,
sinceId: string | null,
limit: number,
channelId: string
}, me: MiLocalUser | null) {
//#region fallback to database //#region fallback to database
const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate) const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), ps.sinceId, ps.untilId)
.andWhere('note.channelId = :channelId', { channelId: channel.id }) .andWhere('note.channelId = :channelId', { channelId: ps.channelId })
.innerJoinAndSelect('note.user', 'user') .innerJoinAndSelect('note.user', 'user')
.leftJoinAndSelect('note.reply', 'reply') .leftJoinAndSelect('note.reply', 'reply')
.leftJoinAndSelect('note.renote', 'renote') .leftJoinAndSelect('note.renote', 'renote')
@ -146,10 +139,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
} }
//#endregion //#endregion
const timeline = await query.limit(ps.limit).getMany(); return await query.limit(ps.limit).getMany();
return await this.noteEntityService.packMany(timeline, me);
//#endregion
});
} }
} }