Skip to content

Commit 552354c

Browse files
u1-liquidtamaina
andcommitted
fix(backend): 古いユーザーキャッシュを使うことへの対策 (misskey-dev#13453)
Co-authored-by: tamaina <[email protected]>
1 parent 4a615ff commit 552354c

File tree

7 files changed

+26
-26
lines changed

7 files changed

+26
-26
lines changed

packages/backend/src/core/AccountMoveService.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import { ApPersonService } from '@/core/activitypub/models/ApPersonService.js';
2121
import { ApDeliverManagerService } from '@/core/activitypub/ApDeliverManagerService.js';
2222
import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
2323
import { UserEntityService } from '@/core/entities/UserEntityService.js';
24-
import { CacheService } from '@/core/CacheService.js';
2524
import { ProxyAccountService } from '@/core/ProxyAccountService.js';
2625
import { FederatedInstanceService } from '@/core/FederatedInstanceService.js';
2726
import { MetaService } from '@/core/MetaService.js';
@@ -61,7 +60,6 @@ export class AccountMoveService {
6160
private instanceChart: InstanceChart,
6261
private metaService: MetaService,
6362
private relayService: RelayService,
64-
private cacheService: CacheService,
6563
private queueService: QueueService,
6664
) {
6765
}
@@ -85,7 +83,7 @@ export class AccountMoveService {
8583
Object.assign(src, update);
8684

8785
// Update cache
88-
this.cacheService.uriPersonCache.set(srcUri, src);
86+
this.globalEventService.publishInternalEvent('localUserUpdated', src);
8987

9088
const srcPerson = await this.apRendererService.renderPerson(src);
9189
const updateAct = this.apRendererService.addContext(this.apRendererService.renderUpdate(srcPerson, src));

packages/backend/src/core/CacheService.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,12 @@ export class CacheService implements OnApplicationShutdown {
129129
switch (type) {
130130
case 'userChangeSuspendedState':
131131
case 'userChangeDeletedState':
132-
case 'remoteUserUpdated': {
132+
case 'remoteUserUpdated':
133+
case 'localUserUpdated': {
133134
const user = await this.usersRepository.findOneBy({ id: body.id });
134135
if (user == null) {
135136
this.userByIdCache.delete(body.id);
137+
this.localUserByIdCache.delete(body.id);
136138
for (const [k, v] of this.uriPersonCache.cache.entries()) {
137139
if (v.value?.id === body.id) {
138140
this.uriPersonCache.delete(k);

packages/backend/src/core/GlobalEventService.ts

+1
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ export interface InternalEventTypes {
212212
userChangeDeletedState: { id: MiUser['id']; isDeleted: MiUser['isDeleted']; };
213213
userTokenRegenerated: { id: MiUser['id']; oldToken: string; newToken: string; };
214214
remoteUserUpdated: { id: MiUser['id']; };
215+
localUserUpdated: { id: MiUser['id']; };
215216
follow: { followerId: MiUser['id']; followeeId: MiUser['id']; };
216217
unfollow: { followerId: MiUser['id']; followeeId: MiUser['id']; };
217218
blockingCreated: { blockerId: MiUser['id']; blockeeId: MiUser['id']; };

packages/backend/src/core/UserFollowingService.ts

+9-18
Original file line numberDiff line numberDiff line change
@@ -100,33 +100,24 @@ export class UserFollowingService implements OnModuleInit {
100100
this.queueService.deliver(followee, content, follower.inbox, false);
101101
}
102102

103-
/**
104-
* ThinUserでなくともユーザーの情報が最新でない場合はこちらを使うべき
105-
*/
106103
@bindThis
107-
public async followByThinUser(
104+
public async follow(
108105
_follower: ThinUser,
109106
_followee: ThinUser,
110-
options: Parameters<typeof this.follow>[2] = {},
111-
) {
112-
const [follower, followee] = await Promise.all([
113-
this.usersRepository.findOneByOrFail({ id: _follower.id }),
114-
this.usersRepository.findOneByOrFail({ id: _followee.id }),
115-
]) as [MiLocalUser | MiRemoteUser, MiLocalUser | MiRemoteUser];
116-
117-
await this.follow(follower, followee, options);
118-
}
119-
120-
@bindThis
121-
public async follow(
122-
follower: MiLocalUser | MiRemoteUser,
123-
followee: MiLocalUser | MiRemoteUser,
124107
{ requestId, silent = false, withReplies }: {
125108
requestId?: string,
126109
silent?: boolean,
127110
withReplies?: boolean,
128111
} = {},
129112
): Promise<void> {
113+
/**
114+
* 必ず最新のユーザー情報を取得する
115+
*/
116+
const [follower, followee] = await Promise.all([
117+
this.usersRepository.findOneByOrFail({ id: _follower.id }),
118+
this.usersRepository.findOneByOrFail({ id: _followee.id }),
119+
]) as [MiLocalUser | MiRemoteUser, MiLocalUser | MiRemoteUser];
120+
130121
if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isRemoteUser(followee)) {
131122
// What?
132123
throw new Error('Remote user cannot follow remote user.');

packages/backend/src/misc/cache.ts

+8
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,10 @@ export class RedisSingleCache<T> {
193193
// TODO: メモリ節約のためあまり参照されないキーを定期的に削除できるようにする?
194194

195195
export class MemoryKVCache<T> {
196+
/**
197+
* データを持つマップ
198+
* @deprecated これを直接操作するべきではない
199+
*/
196200
public cache: Map<string, { date: number; value: T; }>;
197201
private lifetime: number;
198202
private gcIntervalHandle: NodeJS.Timeout;
@@ -207,6 +211,10 @@ export class MemoryKVCache<T> {
207211
}
208212

209213
@bindThis
214+
/**
215+
* Mapにキャッシュをセットします
216+
* @deprecated これを直接呼び出すべきではない。InternalEventなどで変更を全てのプロセス/マシンに通知するべき
217+
*/
210218
public set(key: string, value: T): void {
211219
this.cache.set(key, {
212220
date: Date.now(),

packages/backend/src/queue/processors/RelationshipProcessorService.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export class RelationshipProcessorService {
3535
@bindThis
3636
public async processFollow(job: Bull.Job<RelationshipJobData>): Promise<string> {
3737
this.logger.info(`${job.data.from.id} is trying to follow ${job.data.to.id} ${job.data.withReplies ? 'with replies' : 'without replies'}`);
38-
await this.userFollowingService.followByThinUser(job.data.from, job.data.to, {
38+
await this.userFollowingService.follow(job.data.from, job.data.to, {
3939
requestId: job.data.requestId,
4040
silent: job.data.silent,
4141
withReplies: job.data.withReplies,

packages/backend/src/server/api/endpoints/i/update.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -443,9 +443,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
443443
this.hashtagService.updateUsertags(user, tags);
444444
//#endregion
445445

446-
if (Object.keys(updates).length > 0) await this.usersRepository.update(user.id, updates);
447-
if (Object.keys(updates).includes('alsoKnownAs')) {
448-
this.cacheService.uriPersonCache.set(this.userEntityService.genLocalUserUri(user.id), { ...user, ...updates });
446+
if (Object.keys(updates).length > 0) {
447+
await this.usersRepository.update(user.id, updates);
448+
this.globalEventService.publishInternalEvent('localUserUpdated', { id: user.id });
449449
}
450450

451451
await this.userProfilesRepository.update(user.id, {

0 commit comments

Comments
 (0)