From 34dcb1c51cac8449db90699227497052135486b8 Mon Sep 17 00:00:00 2001 From: Hazelnoot Date: Fri, 4 Jul 2025 09:53:06 -0400 Subject: [PATCH] optimize i/update-remote-user endpoint by fetching from cache --- packages/backend/src/core/CacheService.ts | 13 ++++++++++++- .../endpoints/federation/update-remote-user.ts | 18 +++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/core/CacheService.ts b/packages/backend/src/core/CacheService.ts index 7ba1aba1bc..c29a3ecd7e 100644 --- a/packages/backend/src/core/CacheService.ts +++ b/packages/backend/src/core/CacheService.ts @@ -9,7 +9,7 @@ import { In, IsNull } from 'typeorm'; import type { BlockingsRepository, FollowingsRepository, MutingsRepository, RenoteMutingsRepository, MiUserProfile, UserProfilesRepository, UsersRepository, MiNote, MiFollowing, NoteThreadMutingsRepository } from '@/models/_.js'; import { MemoryKVCache, RedisKVCache } from '@/misc/cache.js'; import { QuantumKVCache } from '@/misc/QuantumKVCache.js'; -import type { MiLocalUser, MiUser } from '@/models/User.js'; +import type { MiLocalUser, MiRemoteUser, MiUser } from '@/models/User.js'; import { DI } from '@/di-symbols.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { bindThis } from '@/decorators.js'; @@ -387,6 +387,17 @@ export class CacheService implements OnApplicationShutdown { }) ?? null; } + @bindThis + public async findRemoteUserById(userId: MiUser['id']): Promise { + const user = await this.findUserById(userId); + + if (user.host == null) { + return null; + } + + return user as MiRemoteUser; + } + @bindThis public async getFollowStats(userId: MiUser['id']): Promise { return await this.userFollowStatsCache.fetch(userId, async () => { diff --git a/packages/backend/src/server/api/endpoints/federation/update-remote-user.ts b/packages/backend/src/server/api/endpoints/federation/update-remote-user.ts index 67fa5ed343..27c3e63ade 100644 --- a/packages/backend/src/server/api/endpoints/federation/update-remote-user.ts +++ b/packages/backend/src/server/api/endpoints/federation/update-remote-user.ts @@ -7,12 +7,22 @@ import { Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { ApPersonService } from '@/core/activitypub/models/ApPersonService.js'; import { GetterService } from '@/server/api/GetterService.js'; +import { CacheService } from '@/core/CacheService.js'; +import { ApiError } from '@/server/api/error.js'; export const meta = { tags: ['federation'], requireCredential: false, + errors: { + noSuchUser: { + message: 'No such user.', + code: 'NO_SUCH_USER', + id: '558ea170-f653-4700-94d0-5a818371d0df', + }, + }, + // Up to 10 calls, then 4 / second. // This allows for reliable automation. limit: { @@ -35,9 +45,15 @@ export default class extends Endpoint { // eslint- constructor( private getterService: GetterService, private apPersonService: ApPersonService, + private readonly cacheService: CacheService, ) { super(meta, paramDef, async (ps) => { - const user = await this.getterService.getRemoteUser(ps.userId); + const user = await this.cacheService.findRemoteUserById(ps.userId); + + if (!user) { + throw new ApiError(meta.errors.noSuchUser); + } + await this.apPersonService.updatePerson(user.uri!); }); }