ãã§ãã¬ãŒã·ã§ã³ã€ã³ã¹ã¿ã³ã¹ãã£ãã·ã¥ç¡å¹åæ©èœ#
æŠèŠ#
Misskey ã®ãã§ãã¬ãŒã·ã§ã³ã·ã¹ãã ã¯ããã§ãã¬ãŒãããã€ã³ã¹ã¿ã³ã¹ã®ã¡ã¿ããŒã¿ã管çããããã®é«åºŠãªãã£ãã·ã¥ç¡å¹åæ©èœãå®è£ ããŠããŸãããã®æ©èœã«ã¯ã管çè ã«ããæç€ºçãªãã£ãã·ã¥ãªã»ããæäœãã€ã³ã¹ã¿ã³ã¹ãã¹ãåã®æ£èŠåã®æ¹åãåé·ãªæŽæ°ãåé¿ããããã®æ©æç¡å¹åã¡ã«ããºã ãå«ãŸããŠããŸãã
ãã£ãã·ã¥ã¢ãŒããã¯ãã£#
2 å±€ãã£ãã·ã³ã°æŠç¥#
ãã§ãã¬ãŒã·ã§ã³ã€ã³ã¹ã¿ã³ã¹ãã£ãã·ã¥ã¯2 å±€ãã£ãã·ã³ã°ã¢ãŒããã¯ãã£ã䜿çšããŸã:
- Redis ãã£ãã·ã¥ïŒãã©ã€ããªïŒ: 30 åã®ã©ã€ãã¿ã€ã
- ã€ã³ã¡ã¢ãªãã£ãã·ã¥ïŒã»ã«ã³ããªïŒ: 3 åã®ã©ã€ãã¿ã€ã
ãã£ãã·ã¥ãšã³ããªã¯ãRedisã« kvcache:federatedInstance:{host} ãšããããŒãã¿ãŒã³ã§ä¿åãããŸãã
ãã£ãã·ã¥å®è£ #
ãã£ãã·ã¥ã¯ãFederatedInstanceServiceå
ã§RedisKVCacheã¯ã©ã¹ã䜿çšããŠå®è£
ãããŠããã3 åããšã«èªåçã«ã¡ã¢ãªãã£ãã·ã¥ã®ã¬ããŒãžã³ã¬ã¯ã·ã§ã³ãå®è¡ãããŸãã
管çè ã«ããæç€ºçãªãã£ãã·ã¥ç¡å¹å#
管ç API ãšã³ããã€ã³ã#
管çè
ã¯admin/federation/update-instance API ãšã³ããã€ã³ããä»ããŠãã€ã³ã¹ã¿ã³ã¹ãã£ãã·ã¥ãæç€ºçã«ãªã»ããã§ããŸãã
ãšã³ããã€ã³ãèŠä»¶:
- Permission: ã¢ãã¬ãŒã¿ãŒããŒã«ãå¿ èŠ
- API Kind:
write:admin:federation - Parameters:
hostïŒå¿ é ïŒãisSuspendedïŒãªãã·ã§ã³ïŒãmoderationNoteïŒãªãã·ã§ã³ïŒ
ãã£ãã·ã¥ã®ã¿ã®ç¡å¹å#
hostãã©ã¡ãŒã¿ã®ã¿ã§åŒã³åºãããå ŽåïŒæŽæ°ãªãïŒããšã³ããã€ã³ãã¯æç€ºçã«ãã£ãã·ã¥ãç¡å¹åããŸã:
if (ps.isSuspended == null && ps.moderationNote == null) {
await this.federatedInstanceService.invalidate(normalizedHost);
return;
}
ç¡å¹åã®å®è£ #
invalidate()ã¡ãœããã¯ããã¹ãåãæ£èŠåããRedis ãšã¡ã¢ãªãã£ãã·ã¥ã®äž¡æ¹ãããšã³ããªãåé€ããŸã:
public async invalidate(host: string): Promise<void> {
const normalizedHost = this.utilityService.normalizeHost(host);
await this.federatedInstanceCache.delete(normalizedHost);
}
ãã¹ã忣èŠåã®æ¹å#
æ£èŠåã¡ãœãã#
ã·ã¹ãã ã¯UtilityService.normalizeHost()ã䜿çšããŠããã¹ãåãæšæºç㪠ASCII 圢åŒã«å€æããŸã:
public normalizeHost(host: string): string {
return punycode.toASCII(host.toLowerCase());
}
ããã«ãã以äžãä¿èšŒãããŸã:
- åœéåãã¡ã€ã³åïŒIDNïŒã punycode ã䜿çšã㊠ASCII ã«å€æããã
- ãã¹ãåãå°æååããã倧æåå°æåãåºå¥ããªããããã³ã°ãå¯èœã«ãªã
- äžè²«ãããã£ãã·ã¥ããŒãšããŒã¿ããŒã¹ã«ãã¯ã¢ãããå®çŸããã
æŽæ°æã®æ£èŠå#
FederatedInstanceService.fetchOrRegister()ã¡ãœããã¯ãããŒã¿ããŒã¹æäœã®åã«ãã¹ãåãæ£èŠåããŸã:
public async fetchOrRegister(host: string): Promise<MiInstance> {
host = this.utilityService.normalizeHost(host);
const cached = await this.federatedInstanceCache.get(host);
if (cached) return cached;
const index = await this.instancesRepository.findOneBy({ host });
// ... ã€ã³ã¹ã¿ã³ã¹ã®äœæãŸãã¯æŽæ°
}
å©ç¹:
- ãã¹ãŠã®ããŒã¿ããŒã¹ã«ãã¯ã¢ãããæ£èŠåããã圢åŒã䜿çšãã
- æ°ããã€ã³ã¹ã¿ã³ã¹ã¬ã³ãŒããæšæºçãªãã¹ãåã§ä¿åããã
- ãã£ãã·ã¥ããŒãæäœå šäœã§äžè²«æ§ãä¿ã€
- host ã«ã©ã ã®ãŠããŒã¯ã€ã³ããã¯ã¹ã«ãããç°ãªã圢åŒã§ãåçã®ãã¹ãåã«ããéè€ã€ã³ã¹ã¿ã³ã¹ã鲿¢ããã
ããŒã¿ããŒã¹å€æŽæã®èªåãã£ãã·ã¥æŽæ°#
update()ã¡ãœããã¯ãããŒã¿ããŒã¹æŽæ°åŸã«èªåçã«ãã£ãã·ã¥ããªãã¬ãã·ã¥ããŸã:
public async update(id: MiInstance['id'], data: Partial<MiInstance>): Promise<void> {
const result = await this.instancesRepository.createQueryBuilder().update()
.set(data)
.where('id = :id', { id })
.returning('*')
.execute()
.then((response) => response.raw[0]);
this.federatedInstanceCache.set(result.host, result);
}
åé·ãªæŽæ°ãåé¿ããããã®æ©æç¡å¹åã¡ã«ããºã #
1. ãã£ãã·ã¥ãããæã®æ©æãªã¿ãŒã³#
fetch()ã¡ãœããã¯ããã£ãã·ã¥ãããããŒã¿ãããå Žåã¯å³åº§ã«è¿ããäžèŠãªããŒã¿ããŒã¹ã¯ãšãªãé²ããŸã:
public async fetch(host: string): Promise<MiInstance | null> {
host = this.utilityService.normalizeHost(host);
const cached = await this.federatedInstanceCache.get(host);
if (cached !== undefined) return cached;
// ãã£ãã·ã¥ã«ãªãå Žåã®ã¿ããŒã¿ããŒã¹ãã¯ãšãª
const index = await this.instancesRepository.findOneBy({ host });
// ...
}
2. æŽæ°åã®å€æ¯èŒ#
管ççšæŽæ°ãšã³ããã€ã³ãã¯ãæŽæ°ãå®è¡ããåã«å€ãæ¯èŒããŸã:
const isSuspendedBefore = instance.suspensionState !== 'none';
const suspensionState = (ps.isSuspended != null && isSuspendedBefore !== ps.isSuspended)
? (ps.isSuspended ? 'manuallySuspended' : 'none')
: undefined;
// å€ãå®éã«å€æŽãããå Žåã®ã¿ãã°ãèšé²
if (ps.isSuspended != null && isSuspendedBefore !== ps.isSuspended) {
// ... ã¢ãã¬ãŒã·ã§ã³ãã°ãšã³ããªãäœæ
}
ããã«ãããå€ãå®éã«å€æŽãããå Žåã®ã¿ã¢ãã¬ãŒã·ã§ã³ãã°ãäœæãããåé·ãªæäœãåæžãããŸãã
3. ã¡ã¿ããŒã¿ååŸã®æéããŒã¹ã¹ããããªã³ã°#
FetchInstanceMetadataServiceã¯ãéå» 24 æé以å
ã«æŽæ°ãããå Žåã¯ã¡ã¿ããŒã¿ã®ååŸãé²ããŸã:
if (!force) {
const _instance = await this.federatedInstanceService.fetchOrRegister(host);
const now = Date.now();
if (_instance && _instance.infoUpdatedAt && (now - _instance.infoUpdatedAt.getTime() < 1000 * 60 * 60 * 24)) {
return; // åé·ãªååŸãã¹ããã
}
}
4. æŽæ°ããããåŠçãã Collapsed Queue#
InboxProcessorServiceã¯ãCollapsedQueueã䜿çšããŠã5 åéã®ãŠã£ã³ããŠå
ã®è€æ°ã®æŽæ°ãªã¯ãšã¹ããããŒãžããŸã:
public collapseUpdateInstanceJobs(oldJob: UpdateInstanceJob, newJob: UpdateInstanceJob) {
const latestRequestReceivedAt = oldJob.latestRequestReceivedAt < newJob.latestRequestReceivedAt
? newJob.latestRequestReceivedAt
: oldJob.latestRequestReceivedAt;
const shouldUnsuspend = oldJob.shouldUnsuspend || newJob.shouldUnsuspend;
return {
latestRequestReceivedAt,
shouldUnsuspend,
};
}
ããã«ãããè€æ°ã®æŽæ°ãåäžã®æäœã«ãããåŠçããããšã§ãåé·ãªããŒã¿ããŒã¹æžã蟌ã¿ãå€§å¹ ã«åæžãããŸãã
5. ç¶æ ããŒã¹ã®æ¡ä»¶ä»ãæŽæ°#
DeliverProcessorServiceã¯ãç¶æ
ãå®éã«å€æŽãããå Žåã®ã¿æŽæ°ããŸã:
if (i.isNotResponding) {
this.federatedInstanceService.update(i.id, {
isNotResponding: false,
notRespondingSince: null,
});
}
ããã«ãããã€ã³ã¹ã¿ã³ã¹ãæ¢ã«æ£ããç¶æ ã«ããå Žåã®äžèŠãªããŒã¿ããŒã¹æžã蟌ã¿ã鲿¢ãããŸãã
ãã§ãã¬ãŒã·ã§ã³æŽ»åäžã®èªåãã£ãã·ã¥æŽæ°#
ãã£ãã·ã¥ã¯ãããŸããŸãªãã§ãã¬ãŒã·ã§ã³æŽ»åäžã«èªåçã«æŽæ°ãããŸãïŒåãªãç¡å¹åã§ã¯ãããŸããïŒ:
é ä¿¡åŠç#
DeliverProcessorServiceã¯ãé
ä¿¡çµæã«åºã¥ããŠã€ã³ã¹ã¿ã³ã¹ã¹ããŒã¿ã¹ãæŽæ°ããŸã:
isNotRespondingãšnotRespondingSinceãã£ãŒã«ããæŽæ°- 1 é±é以äžå¿çããªãã€ã³ã¹ã¿ã³ã¹ãèªåãµã¹ãã³ã
- HTTP 410ïŒGoneïŒã¹ããŒã¿ã¹ãè¿ãã€ã³ã¹ã¿ã³ã¹ãèªåãµã¹ãã³ã
åä¿¡åŠç#
InboxProcessorServiceã¯ãã€ã³ã¹ã¿ã³ã¹ã®ã¢ã¯ãã£ããã£ãæŽæ°ããŸã:
latestRequestReceivedAtã¿ã€ã ã¹ã¿ã³ããæŽæ°autoSuspendedForNotRespondingç¶æ ã ã£ãã€ã³ã¹ã¿ã³ã¹ãèªåçã«ãµã¹ãã³ãè§£é€isNotRespondingã false ã«èšå®
ãã£ãã·ã¥ã©ã€ããµã€ã¯ã«ç®¡ç#
ãµãŒãã¹ã«ã¯é©åãªã¯ãªãŒã³ã¢ããã¡ã«ããºã ãå«ãŸããŠããŸã:
dispose()- ãã£ãã·ã¥ãªãœãŒã¹ãæåã§ã¯ãªãŒã³ã¢ããonApplicationShutdown()- ã¢ããªã±ãŒã·ã§ã³ã·ã£ããããŠã³æã«èªåã¯ãªãŒã³ã¢ãã- ã¡ã¢ãªãã£ãã·ã¥ã«ã¯ãæéåããšã³ããªãåé€ããããã®3 åããšã®ã¬ããŒãžã³ã¬ã¯ã·ã§ã³ãå®è£ ãããŠããŸã
ãã£ãã·ã¥ç¡å¹åãããŒã®å³#
ãŸãšã#
ãã§ãã¬ãŒã·ã§ã³ã€ã³ã¹ã¿ã³ã¹ãã£ãã·ã¥ç¡å¹åæ©èœã¯ã以äžãæäŸããŸã:
- æç€ºçãªç®¡çå¶åŸ¡ - API ãšã³ããã€ã³ããä»ãããã£ãã·ã¥ãªã»ãã
- æ¹åããããã¹ã忣èŠå - äžè²«ãããã£ãã·ã¥ããŒãä¿èšŒããéè€ã¬ã³ãŒãã鲿¢
- è€æ°ã®æ©æç¡å¹åã¡ã«ããºã - ãã£ãã·ã¥ãããã倿¯èŒãæéããŒã¹ã¹ããããªã³ã°ãCollapsed Queueãæ¡ä»¶ä»ãæŽæ°ãå«ã
- èªåãã£ãã·ã¥ãªãã¬ãã·ã¥ - ãã§ãã¬ãŒã·ã§ã³æŽ»åäžã«ããŒã¿ãææ°ã«ä¿ã€
- é©åãªã©ã€ããµã€ã¯ã«ç®¡ç - èªåã¯ãªãŒã³ã¢ãããšã¬ããŒãžã³ã¬ã¯ã·ã§ã³
ãããã®ã¡ã«ããºã ã«ãããã·ã¹ãã ã¯é«ãããã©ãŒãã³ã¹ãç¶æããªãããããŒã¿ã®äžè²«æ§ãšæ£ç¢ºæ§ã確ä¿ããŸãã