diff --git a/CHANGELOG.md b/CHANGELOG.md index f41188a4d..8da8d3fac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -92,6 +92,7 @@ - Fix: ジョブに関する設定の名前を修正 relashionshipJobPerSec -> relationshipJobPerSec - Fix: コントロールパネル->モデレーション->「誰でも新規登録できるようにする」の初期値をONからOFFに変更 #13122 - Enhance: 連合向けのノート配信を軽量化 #13192 +- Fix: リモートユーザーが復活してもキャッシュにより該当ユーザーのActivityが受け入れられないのを修正 #13273 ### Service Worker - Enhance: オフライン表示のデザインを改善・多言語対応 diff --git a/packages/backend/src/core/CacheService.ts b/packages/backend/src/core/CacheService.ts index ef3abec19..78bb4f70e 100644 --- a/packages/backend/src/core/CacheService.ts +++ b/packages/backend/src/core/CacheService.ts @@ -85,6 +85,7 @@ export class CacheService implements OnApplicationShutdown { this.uriPersonCache = new MemoryKVCache(Infinity, { toMapConverter: user => { if (user === null) return null; + if (user.isDeleted) return null; userByIdCache.set(user.id, user); return user.id; @@ -160,16 +161,25 @@ export class CacheService implements OnApplicationShutdown { switch (type) { case 'userChangeSuspendedState': case 'remoteUserUpdated': { - const user = await this.usersRepository.findOneByOrFail({ id: body.id }); - this.userByIdCache.set(user.id, user); - for (const [k, v] of this.uriPersonCache.cache.entries()) { - if (v.value === user.id) { - this.uriPersonCache.set(k, user); + const user = await this.usersRepository.findOneBy({ id: body.id }); + if (user == null) { + this.userByIdCache.delete(body.id); + for (const [k, v] of this.uriPersonCache.cache.entries()) { + if (v.value === body.id) { + this.uriPersonCache.delete(k); + } + } + } else { + this.userByIdCache.set(user.id, user); + for (const [k, v] of this.uriPersonCache.cache.entries()) { + if (v.value === user.id) { + this.uriPersonCache.set(k, user); + } + } + if (this.userEntityService.isLocalUser(user)) { + this.localUserByNativeTokenCache.set(user.token!, user); + this.localUserByIdCache.set(user.id, user); } - } - if (this.userEntityService.isLocalUser(user)) { - this.localUserByNativeTokenCache.set(user.token!, user); - this.localUserByIdCache.set(user.id, user); } break; } diff --git a/packages/backend/src/core/activitypub/ApDbResolverService.ts b/packages/backend/src/core/activitypub/ApDbResolverService.ts index 143f89c36..f6b70ead4 100644 --- a/packages/backend/src/core/activitypub/ApDbResolverService.ts +++ b/packages/backend/src/core/activitypub/ApDbResolverService.ts @@ -106,12 +106,12 @@ export class ApDbResolverService implements OnApplicationShutdown { return await this.cacheService.userByIdCache.fetchMaybe( parsed.id, - () => this.usersRepository.findOneBy({ id: parsed.id }).then(x => x ?? undefined), + () => this.usersRepository.findOneBy({ id: parsed.id, isDeleted: false }).then(x => x ?? undefined), ) as MiLocalUser | undefined ?? null; } else { return await this.cacheService.uriPersonCache.fetch( parsed.uri, - () => this.usersRepository.findOneBy({ uri: parsed.uri }), + () => this.usersRepository.findOneBy({ uri: parsed.uri, isDeleted: false }), ) as MiRemoteUser | null; } } @@ -136,8 +136,12 @@ export class ApDbResolverService implements OnApplicationShutdown { if (key == null) return null; + const user = await this.cacheService.findUserById(key.userId).catch(() => null) as MiRemoteUser | null; + if (user == null) return null; + if (user.isDeleted) return null; + return { - user: await this.cacheService.findUserById(key.userId) as MiRemoteUser, + user, key, }; } @@ -151,6 +155,7 @@ export class ApDbResolverService implements OnApplicationShutdown { key: MiUserPublickey | null; } | null> { const user = await this.apPersonService.resolvePerson(uri) as MiRemoteUser; + if (user.isDeleted) return null; const key = await this.publicKeyByUserIdCache.fetch( user.id, diff --git a/packages/backend/src/core/activitypub/ApInboxService.ts b/packages/backend/src/core/activitypub/ApInboxService.ts index 526b04b29..1cc54b6ff 100644 --- a/packages/backend/src/core/activitypub/ApInboxService.ts +++ b/packages/backend/src/core/activitypub/ApInboxService.ts @@ -35,6 +35,8 @@ import { ApResolverService } from './ApResolverService.js'; import { ApAudienceService } from './ApAudienceService.js'; import { ApPersonService } from './models/ApPersonService.js'; import { ApQuestionService } from './models/ApQuestionService.js'; +import { CacheService } from '@/core/CacheService.js'; +import { GlobalEventService } from '@/core/GlobalEventService.js'; import type { Resolver } from './ApResolverService.js'; import type { IAccept, IAdd, IAnnounce, IBlock, ICreate, IDelete, IFlag, IFollow, ILike, IObject, IReject, IRemove, IUndo, IUpdate, IMove } from './type.js'; @@ -82,6 +84,8 @@ export class ApInboxService { private apPersonService: ApPersonService, private apQuestionService: ApQuestionService, private queueService: QueueService, + private cacheService: CacheService, + private globalEventService: GlobalEventService, ) { this.logger = this.apLoggerService.logger; } @@ -479,6 +483,8 @@ export class ApInboxService { isDeleted: true, }); + this.globalEventService.publishInternalEvent('remoteUserUpdated', { id: actor.id }); + return `ok: queued ${job.name} ${job.id}`; }