perf(federation): Use hint for getAuthUserFromApId (#13470)

* Hint for getAuthUserFromApId

* とどのつまりこれでいいのか?
This commit is contained in:
MeiMei 2024-02-28 16:44:01 +09:00 committed by GitHub
parent 59ae735169
commit aaacfabc1b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 13 additions and 60 deletions

View file

@ -35,7 +35,6 @@ export type UriParseResult = {
@Injectable()
export class ApDbResolverService implements OnApplicationShutdown {
private publicKeyCache: MemoryKVCache<MiUserPublickey | null>;
private publicKeyByUserIdCache: MemoryKVCache<MiUserPublickey[] | null>;
constructor(
@ -54,7 +53,6 @@ export class ApDbResolverService implements OnApplicationShutdown {
private cacheService: CacheService,
private apPersonService: ApPersonService,
) {
this.publicKeyCache = new MemoryKVCache<MiUserPublickey | null>(1e3 * 60 * 20); // 20分
this.publicKeyByUserIdCache = new MemoryKVCache<MiUserPublickey[] | null>(1e3 * 60 * 20); // 20分
}
@ -116,41 +114,11 @@ export class ApDbResolverService implements OnApplicationShutdown {
}
}
/**
* AP KeyId => Misskey User and Key
*/
@bindThis
public async getAuthUserFromKeyId(keyId: string): Promise<{
user: MiRemoteUser;
key: MiUserPublickey;
} | null> {
const key = await this.publicKeyCache.fetch(keyId, async () => {
const key = await this.userPublickeysRepository.findOneBy({
keyId,
});
if (key == null) return null;
return key;
}, key => key != null);
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,
key,
};
}
/**
* AP Actor id => Misskey User and Key
*/
@bindThis
public async getAuthUserFromApId(uri: string): Promise<{
public async getAuthUserFromApId(uri: string, keyId?: string): Promise<{
user: MiRemoteUser;
key: MiUserPublickey | null;
} | null> {
@ -170,6 +138,7 @@ export class ApDbResolverService implements OnApplicationShutdown {
keys[0] :
keys.find(x => {
try {
if (x.keyId === keyId) return true;
const url = new URL(x.keyId);
const path = url.pathname.split('/').pop()?.toLowerCase();
if (url.hash) {
@ -193,16 +162,10 @@ export class ApDbResolverService implements OnApplicationShutdown {
@bindThis
public refreshCacheByUserId(userId: MiUser['id']): void {
this.publicKeyByUserIdCache.delete(userId);
for (const [k, v] of this.publicKeyCache.cache.entries()) {
if (v.value?.userId === userId) {
this.publicKeyCache.delete(k);
}
}
}
@bindThis
public dispose(): void {
this.publicKeyCache.dispose();
this.publicKeyByUserIdCache.dispose();
}

View file

@ -77,20 +77,18 @@ export class InboxProcessorService {
let authUser: {
user: MiRemoteUser;
key: MiUserPublickey | null;
} | null = await this.apDbResolverService.getAuthUserFromKeyId(signature.keyId);
} | null = null;
// keyIdでわからなければ、activity.actorを元にDBから取得 || activity.actorを元にリモートから取得
if (authUser == null) {
try {
authUser = await this.apDbResolverService.getAuthUserFromApId(getApId(activity.actor));
} catch (err) {
// 対象が4xxならスキップ
if (err instanceof StatusError) {
if (!err.isRetryable) {
throw new Bull.UnrecoverableError(`skip: Ignored deleted actors on both ends ${activity.actor} - ${err.statusCode}`);
}
throw new Error(`Error in actor ${activity.actor} - ${err.statusCode}`);
try {
authUser = await this.apDbResolverService.getAuthUserFromApId(getApId(activity.actor), signature.keyId);
} catch (err) {
// 対象が4xxならスキップ
if (err instanceof StatusError) {
if (!err.isRetryable) {
throw new Bull.UnrecoverableError(`skip: Ignored deleted actors on both ends ${activity.actor} - ${err.statusCode}`);
}
throw new Error(`Error in actor ${activity.actor} - ${err.statusCode}`);
}
}
@ -110,21 +108,13 @@ export class InboxProcessorService {
// また、signatureのsignerは、activity.actorと一致する必要がある
if (!httpSignatureValidated || authUser.user.uri !== activity.actor) {
// 一致しなくても、でもLD-Signatureがありそうならそっちも見る
if (activity.signature) {
if (activity.signature?.creator) {
if (activity.signature.type !== 'RsaSignature2017') {
throw new Bull.UnrecoverableError(`skip: unsupported LD-signature type ${activity.signature.type}`);
}
// activity.signature.creator: https://example.oom/users/user#main-key
// みたいになっててUserを引っ張れば公開キーも入ることを期待する
if (activity.signature.creator) {
const candicate = activity.signature.creator.replace(/#.*/, '');
const user = await this.apPersonService.resolvePerson(candicate).catch(() => null);
if (user) this.apDbResolverService.refreshCacheByUserId(user.id);
}
authUser = await this.apDbResolverService.getAuthUserFromApId(activity.signature.creator.replace(/#.*/, ''));
// keyIdからLD-Signatureのユーザーを取得
authUser = await this.apDbResolverService.getAuthUserFromKeyId(activity.signature.creator);
if (authUser == null) {
throw new Bull.UnrecoverableError('skip: LD-Signatureのユーザーが取得できませんでした');
}