summaryrefslogtreecommitdiff
path: root/packages/backend/src/core
diff options
context:
space:
mode:
authorYuriha <121590760+yuriha-chan@users.noreply.github.com>2023-07-07 23:28:27 +0900
committerGitHub <noreply@github.com>2023-07-07 23:28:27 +0900
commit4c879b3a336aee944cf611a9d01649d62a00d622 (patch)
tree4a5c6a305bf103a51758d0c7f671b0928268e730 /packages/backend/src/core
parentfix(client): ZenUIでポップアップの表示位置がおかしい問題... (diff)
downloadsharkey-4c879b3a336aee944cf611a9d01649d62a00d622.tar.gz
sharkey-4c879b3a336aee944cf611a9d01649d62a00d622.tar.bz2
sharkey-4c879b3a336aee944cf611a9d01649d62a00d622.zip
perf(backend): Improve performance of FetchInstanceMetadata (#11128)
* Perf: Avoid retries to acquire lock in fetchInstanceMetadata * Fix * Add Changelog * Fix typo * Fix lint * 記法をMisskey式にする * ???? * refactor https://github.com/misskey-dev/misskey/pull/11128#pullrequestreview-1518059366 * refactor * getいらない? * fix * fix * Update CHANGELOG.md * clean up --------- Co-authored-by: tamaina <tamaina@hotmail.co.jp>
Diffstat (limited to 'packages/backend/src/core')
-rw-r--r--packages/backend/src/core/AppLockService.ts5
-rw-r--r--packages/backend/src/core/FetchInstanceMetadataService.ts45
2 files changed, 27 insertions, 23 deletions
diff --git a/packages/backend/src/core/AppLockService.ts b/packages/backend/src/core/AppLockService.ts
index 8dd805552b..6ccaec26ba 100644
--- a/packages/backend/src/core/AppLockService.ts
+++ b/packages/backend/src/core/AppLockService.ts
@@ -33,11 +33,6 @@ export class AppLockService {
}
@bindThis
- public getFetchInstanceMetadataLock(host: string, timeout = 30 * 1000): Promise<() => void> {
- return this.lock(`instance:${host}`, timeout);
- }
-
- @bindThis
public getChartInsertLock(lockKey: string, timeout = 30 * 1000): Promise<() => void> {
return this.lock(`chart-insert:${lockKey}`, timeout);
}
diff --git a/packages/backend/src/core/FetchInstanceMetadataService.ts b/packages/backend/src/core/FetchInstanceMetadataService.ts
index 9de633350b..96ee77d056 100644
--- a/packages/backend/src/core/FetchInstanceMetadataService.ts
+++ b/packages/backend/src/core/FetchInstanceMetadataService.ts
@@ -3,8 +3,6 @@ import { Inject, Injectable } from '@nestjs/common';
import { JSDOM } from 'jsdom';
import tinycolor from 'tinycolor2';
import type { Instance } from '@/models/entities/Instance.js';
-import type { InstancesRepository } from '@/models/index.js';
-import { AppLockService } from '@/core/AppLockService.js';
import type Logger from '@/logger.js';
import { DI } from '@/di-symbols.js';
import { LoggerService } from '@/core/LoggerService.js';
@@ -12,6 +10,7 @@ import { HttpRequestService } from '@/core/HttpRequestService.js';
import { bindThis } from '@/decorators.js';
import { FederatedInstanceService } from '@/core/FederatedInstanceService.js';
import type { DOMWindow } from 'jsdom';
+import * as Redis from 'ioredis';
type NodeInfo = {
openRegistrations?: unknown;
@@ -37,33 +36,43 @@ export class FetchInstanceMetadataService {
private logger: Logger;
constructor(
- @Inject(DI.instancesRepository)
- private instancesRepository: InstancesRepository,
-
- private appLockService: AppLockService,
private httpRequestService: HttpRequestService,
private loggerService: LoggerService,
private federatedInstanceService: FederatedInstanceService,
+ @Inject(DI.redis)
+ private redisClient: Redis.Redis,
) {
this.logger = this.loggerService.getLogger('metadata', 'cyan');
}
@bindThis
+ public async tryLock(host: string): Promise<boolean> {
+ const mutex = await this.redisClient.set(`fetchInstanceMetadata:mutex:${host}`, '1', 'GET');
+ return mutex !== '1';
+ }
+
+ @bindThis
+ public unlock(host: string): Promise<'OK'> {
+ return this.redisClient.set(`fetchInstanceMetadata:mutex:${host}`, '0');
+ }
+
+ @bindThis
public async fetchInstanceMetadata(instance: Instance, force = false): Promise<void> {
- const unlock = await this.appLockService.getFetchInstanceMetadataLock(instance.host);
-
- if (!force) {
- const _instance = await this.instancesRepository.findOneBy({ host: instance.host });
- const now = Date.now();
- if (_instance && _instance.infoUpdatedAt && (now - _instance.infoUpdatedAt.getTime() < 1000 * 60 * 60 * 24)) {
- unlock();
- return;
+ const host = instance.host;
+ // Acquire mutex to ensure no parallel runs
+ if (!await this.tryLock(host)) return;
+ try {
+ if (!force) {
+ const _instance = await this.federatedInstanceService.fetch(host);
+ const now = Date.now();
+ if (_instance && _instance.infoUpdatedAt && (now - _instance.infoUpdatedAt.getTime() < 1000 * 60 * 60 * 24)) {
+ // unlock at the finally caluse
+ return;
+ }
}
- }
- this.logger.info(`Fetching metadata of ${instance.host} ...`);
+ this.logger.info(`Fetching metadata of ${instance.host} ...`);
- try {
const [info, dom, manifest] = await Promise.all([
this.fetchNodeinfo(instance).catch(() => null),
this.fetchDom(instance).catch(() => null),
@@ -104,7 +113,7 @@ export class FetchInstanceMetadataService {
} catch (e) {
this.logger.error(`Failed to update metadata of ${instance.host}: ${e}`);
} finally {
- unlock();
+ await this.unlock(host);
}
}