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

View File

@ -5,7 +5,6 @@
import { Inject, Injectable } from '@nestjs/common';
import { In } from 'typeorm';
import * as Redis from 'ioredis';
import { DI } from '@/di-symbols.js';
import type { Config } from '@/config.js';
import { UserFollowingService } from '@/core/UserFollowingService.js';
@ -15,7 +14,6 @@ import { NotePiningService } from '@/core/NotePiningService.js';
import { UserBlockingService } from '@/core/UserBlockingService.js';
import { NoteDeleteService } from '@/core/NoteDeleteService.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 type Logger from '@/logger.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 { AbuseReportService } from '@/core/AbuseReportService.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 { ApNoteService } from './models/ApNoteService.js';
import { ApLoggerService } from './ApLoggerService.js';
@ -49,9 +48,6 @@ export class ApInboxService {
@Inject(DI.config)
private config: Config,
@Inject(DI.redis)
private redisClient: Redis.Redis,
@Inject(DI.usersRepository)
private usersRepository: UsersRepository,
@ -85,6 +81,7 @@ export class ApInboxService {
private apQuestionService: ApQuestionService,
private queueService: QueueService,
private globalEventService: GlobalEventService,
private appLockService: AppLockService,
) {
this.logger = this.apLoggerService.logger;
}
@ -311,7 +308,7 @@ export class ApInboxService {
// アナウンス先が許可されているかチェック
if (!this.utilityService.isFederationAllowedUri(uri)) return;
const unlock = await acquireApObjectLock(this.redisClient, uri);
const unlock = await this.appLockService.getApLock(uri);
try {
// 既に同じURIを持つものが登録されていないかチェック
@ -438,7 +435,7 @@ export class ApInboxService {
}
}
const unlock = await acquireApObjectLock(this.redisClient, uri);
const unlock = await this.appLockService.getApLock(uri);
try {
const exist = await this.apNoteService.fetchNote(note);
@ -522,7 +519,7 @@ export class ApInboxService {
private async deleteNote(actor: MiRemoteUser, uri: string): Promise<string> {
this.logger.info(`Deleting the Note: ${uri}`);
const unlock = await acquireApObjectLock(this.redisClient, uri);
const unlock = await this.appLockService.getApLock(uri);
try {
const note = await this.apDbResolverService.getNoteFromApId(uri);

View File

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