Restore AppLockService and wrap acquireApObjectLock

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2025-11-30 00:40:02 +00:00
parent 2a23054249
commit 89140c552f
4 changed files with 53 additions and 14 deletions

View File

@ -0,0 +1,39 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { Inject, Injectable } from '@nestjs/common';
import * as Redis from 'ioredis';
import { DI } from '@/di-symbols.js';
import { acquireApObjectLock, acquireChartInsertLock } from '@/misc/distributed-lock.js';
import { bindThis } from '@/decorators.js';
@Injectable()
export class AppLockService {
constructor(
@Inject(DI.redis)
private redisClient: Redis.Redis,
) {
}
/**
* Get AP Object lock
* @param uri AP object ID
* @returns Unlock function
*/
@bindThis
public getApLock(uri: string): Promise<() => Promise<void>> {
return acquireApObjectLock(this.redisClient, uri);
}
/**
* Get chart insert lock
* @param lockKey Lock key
* @returns Unlock function
*/
@bindThis
public getChartInsertLock(lockKey: string): Promise<() => Promise<void>> {
return acquireChartInsertLock(this.redisClient, lockKey);
}
}

View File

@ -19,6 +19,7 @@ import { ChannelMutingService } from '@/core/ChannelMutingService.js';
import { AccountMoveService } from './AccountMoveService.js'; import { AccountMoveService } from './AccountMoveService.js';
import { AccountUpdateService } from './AccountUpdateService.js'; import { AccountUpdateService } from './AccountUpdateService.js';
import { AiService } from './AiService.js'; import { AiService } from './AiService.js';
import { AppLockService } from './AppLockService.js';
import { AnnouncementService } from './AnnouncementService.js'; import { AnnouncementService } from './AnnouncementService.js';
import { AntennaService } from './AntennaService.js'; import { AntennaService } from './AntennaService.js';
import { AchievementService } from './AchievementService.js'; import { AchievementService } from './AchievementService.js';
@ -163,6 +164,7 @@ const $AbuseReportNotificationService: Provider = { provide: 'AbuseReportNotific
const $AccountMoveService: Provider = { provide: 'AccountMoveService', useExisting: AccountMoveService }; const $AccountMoveService: Provider = { provide: 'AccountMoveService', useExisting: AccountMoveService };
const $AccountUpdateService: Provider = { provide: 'AccountUpdateService', useExisting: AccountUpdateService }; const $AccountUpdateService: Provider = { provide: 'AccountUpdateService', useExisting: AccountUpdateService };
const $AiService: Provider = { provide: 'AiService', useExisting: AiService }; const $AiService: Provider = { provide: 'AiService', useExisting: AiService };
const $AppLockService: Provider = { provide: 'AppLockService', useExisting: AppLockService };
const $AnnouncementService: Provider = { provide: 'AnnouncementService', useExisting: AnnouncementService }; const $AnnouncementService: Provider = { provide: 'AnnouncementService', useExisting: AnnouncementService };
const $AntennaService: Provider = { provide: 'AntennaService', useExisting: AntennaService }; const $AntennaService: Provider = { provide: 'AntennaService', useExisting: AntennaService };
const $AchievementService: Provider = { provide: 'AchievementService', useExisting: AchievementService }; const $AchievementService: Provider = { provide: 'AchievementService', useExisting: AchievementService };
@ -316,6 +318,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
AccountMoveService, AccountMoveService,
AccountUpdateService, AccountUpdateService,
AiService, AiService,
AppLockService,
AnnouncementService, AnnouncementService,
AntennaService, AntennaService,
AchievementService, AchievementService,
@ -465,6 +468,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$AccountMoveService, $AccountMoveService,
$AccountUpdateService, $AccountUpdateService,
$AiService, $AiService,
$AppLockService,
$AnnouncementService, $AnnouncementService,
$AntennaService, $AntennaService,
$AchievementService, $AchievementService,
@ -615,6 +619,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
AccountMoveService, AccountMoveService,
AccountUpdateService, AccountUpdateService,
AiService, AiService,
AppLockService,
AnnouncementService, AnnouncementService,
AntennaService, AntennaService,
AchievementService, AchievementService,
@ -763,6 +768,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$AccountMoveService, $AccountMoveService,
$AccountUpdateService, $AccountUpdateService,
$AiService, $AiService,
$AppLockService,
$AnnouncementService, $AnnouncementService,
$AntennaService, $AntennaService,
$AchievementService, $AchievementService,

View File

@ -5,7 +5,6 @@
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import { In } from 'typeorm'; import { In } from 'typeorm';
import * as Redis from 'ioredis';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import type { Config } from '@/config.js'; import type { Config } from '@/config.js';
import { UserFollowingService } from '@/core/UserFollowingService.js'; import { UserFollowingService } from '@/core/UserFollowingService.js';
@ -15,7 +14,6 @@ import { NotePiningService } from '@/core/NotePiningService.js';
import { UserBlockingService } from '@/core/UserBlockingService.js'; import { UserBlockingService } from '@/core/UserBlockingService.js';
import { NoteDeleteService } from '@/core/NoteDeleteService.js'; import { NoteDeleteService } from '@/core/NoteDeleteService.js';
import { NoteCreateService } from '@/core/NoteCreateService.js'; import { NoteCreateService } from '@/core/NoteCreateService.js';
import { acquireApObjectLock } from '@/misc/distributed-lock.js';
import { concat, toArray, toSingle, unique } from '@/misc/prelude/array.js'; import { concat, toArray, toSingle, unique } from '@/misc/prelude/array.js';
import type Logger from '@/logger.js'; import type Logger from '@/logger.js';
import { IdService } from '@/core/IdService.js'; import { IdService } from '@/core/IdService.js';
@ -30,6 +28,7 @@ import type { MiRemoteUser } from '@/models/User.js';
import { GlobalEventService } from '@/core/GlobalEventService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js';
import { AbuseReportService } from '@/core/AbuseReportService.js'; import { AbuseReportService } from '@/core/AbuseReportService.js';
import { IdentifiableError } from '@/misc/identifiable-error.js'; import { IdentifiableError } from '@/misc/identifiable-error.js';
import { AppLockService } from '@/core/AppLockService.js';
import { getApHrefNullable, getApId, getApIds, getApType, isAccept, isActor, isAdd, isAnnounce, isBlock, isCollection, isCollectionOrOrderedCollection, isCreate, isDelete, isFlag, isFollow, isLike, isMove, isPost, isReject, isRemove, isTombstone, isUndo, isUpdate, validActor, validPost } from './type.js'; import { getApHrefNullable, getApId, getApIds, getApType, isAccept, isActor, isAdd, isAnnounce, isBlock, isCollection, isCollectionOrOrderedCollection, isCreate, isDelete, isFlag, isFollow, isLike, isMove, isPost, isReject, isRemove, isTombstone, isUndo, isUpdate, validActor, validPost } from './type.js';
import { ApNoteService } from './models/ApNoteService.js'; import { ApNoteService } from './models/ApNoteService.js';
import { ApLoggerService } from './ApLoggerService.js'; import { ApLoggerService } from './ApLoggerService.js';
@ -49,9 +48,6 @@ export class ApInboxService {
@Inject(DI.config) @Inject(DI.config)
private config: Config, private config: Config,
@Inject(DI.redis)
private redisClient: Redis.Redis,
@Inject(DI.usersRepository) @Inject(DI.usersRepository)
private usersRepository: UsersRepository, private usersRepository: UsersRepository,
@ -85,6 +81,7 @@ export class ApInboxService {
private apQuestionService: ApQuestionService, private apQuestionService: ApQuestionService,
private queueService: QueueService, private queueService: QueueService,
private globalEventService: GlobalEventService, private globalEventService: GlobalEventService,
private appLockService: AppLockService,
) { ) {
this.logger = this.apLoggerService.logger; this.logger = this.apLoggerService.logger;
} }
@ -311,7 +308,7 @@ export class ApInboxService {
// アナウンス先が許可されているかチェック // アナウンス先が許可されているかチェック
if (!this.utilityService.isFederationAllowedUri(uri)) return; if (!this.utilityService.isFederationAllowedUri(uri)) return;
const unlock = await acquireApObjectLock(this.redisClient, uri); const unlock = await this.appLockService.getApLock(uri);
try { try {
// 既に同じURIを持つものが登録されていないかチェック // 既に同じURIを持つものが登録されていないかチェック
@ -438,7 +435,7 @@ export class ApInboxService {
} }
} }
const unlock = await acquireApObjectLock(this.redisClient, uri); const unlock = await this.appLockService.getApLock(uri);
try { try {
const exist = await this.apNoteService.fetchNote(note); const exist = await this.apNoteService.fetchNote(note);
@ -522,7 +519,7 @@ export class ApInboxService {
private async deleteNote(actor: MiRemoteUser, uri: string): Promise<string> { private async deleteNote(actor: MiRemoteUser, uri: string): Promise<string> {
this.logger.info(`Deleting the Note: ${uri}`); this.logger.info(`Deleting the Note: ${uri}`);
const unlock = await acquireApObjectLock(this.redisClient, uri); const unlock = await this.appLockService.getApLock(uri);
try { try {
const note = await this.apDbResolverService.getNoteFromApId(uri); const note = await this.apDbResolverService.getNoteFromApId(uri);

View File

@ -5,13 +5,11 @@
import { forwardRef, Inject, Injectable } from '@nestjs/common'; import { forwardRef, Inject, Injectable } from '@nestjs/common';
import { In } from 'typeorm'; import { In } from 'typeorm';
import * as Redis from 'ioredis';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import type { PollsRepository, EmojisRepository, MiMeta } from '@/models/_.js'; import type { PollsRepository, EmojisRepository, MiMeta } from '@/models/_.js';
import type { Config } from '@/config.js'; import type { Config } from '@/config.js';
import type { MiRemoteUser } from '@/models/User.js'; import type { MiRemoteUser } from '@/models/User.js';
import type { MiNote } from '@/models/Note.js'; import type { MiNote } from '@/models/Note.js';
import { acquireApObjectLock } from '@/misc/distributed-lock.js';
import { toArray, toSingle, unique } from '@/misc/prelude/array.js'; import { toArray, toSingle, unique } from '@/misc/prelude/array.js';
import type { MiEmoji } from '@/models/Emoji.js'; import type { MiEmoji } from '@/models/Emoji.js';
import type { MiDriveFile } from '@/models/DriveFile.js'; import type { MiDriveFile } from '@/models/DriveFile.js';
@ -24,6 +22,7 @@ import { UtilityService } from '@/core/UtilityService.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { checkHttps } from '@/misc/check-https.js'; import { checkHttps } from '@/misc/check-https.js';
import { IdentifiableError } from '@/misc/identifiable-error.js'; import { IdentifiableError } from '@/misc/identifiable-error.js';
import { AppLockService } from '@/core/AppLockService.js';
import { getOneApId, getApId, getOneApHrefNullable, validPost, isEmoji, getApType } from '../type.js'; import { getOneApId, getApId, getOneApHrefNullable, validPost, isEmoji, getApType } from '../type.js';
import { ApLoggerService } from '../ApLoggerService.js'; import { ApLoggerService } from '../ApLoggerService.js';
import { ApMfmService } from '../ApMfmService.js'; import { ApMfmService } from '../ApMfmService.js';
@ -49,9 +48,6 @@ export class ApNoteService {
@Inject(DI.meta) @Inject(DI.meta)
private meta: MiMeta, private meta: MiMeta,
@Inject(DI.redis)
private redisClient: Redis.Redis,
@Inject(DI.pollsRepository) @Inject(DI.pollsRepository)
private pollsRepository: PollsRepository, private pollsRepository: PollsRepository,
@ -75,6 +71,7 @@ export class ApNoteService {
private noteCreateService: NoteCreateService, private noteCreateService: NoteCreateService,
private apDbResolverService: ApDbResolverService, private apDbResolverService: ApDbResolverService,
private apLoggerService: ApLoggerService, private apLoggerService: ApLoggerService,
private appLockService: AppLockService,
) { ) {
this.logger = this.apLoggerService.logger; this.logger = this.apLoggerService.logger;
} }
@ -357,7 +354,7 @@ export class ApNoteService {
throw new StatusError('blocked host', 451); throw new StatusError('blocked host', 451);
} }
const unlock = await acquireApObjectLock(this.redisClient, uri); const unlock = await this.appLockService.getApLock(uri);
try { try {
//#region このサーバーに既に登録されていたらそれを返す //#region このサーバーに既に登録されていたらそれを返す