merge: Fix unique constraint error when processing a flurry of note pinning activities (!1024)

View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/1024

Approved-by: dakkar <dakkar@thenautilus.net>
Approved-by: Marie <github@yuugi.dev>
This commit is contained in:
Marie 2025-05-12 10:30:44 +00:00
commit 4430c12e0e

View file

@ -10,7 +10,7 @@ import { IdentifiableError } from '@/misc/identifiable-error.js';
import type { MiUser } from '@/models/User.js';
import type { MiNote } from '@/models/Note.js';
import { IdService } from '@/core/IdService.js';
import type { MiUserNotePining } from '@/models/UserNotePining.js';
import { MiUserNotePining } from '@/models/UserNotePining.js';
import { RelayService } from '@/core/RelayService.js';
import type { Config } from '@/config.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
@ -18,6 +18,7 @@ import { ApDeliverManagerService } from '@/core/activitypub/ApDeliverManagerServ
import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
import { bindThis } from '@/decorators.js';
import { RoleService } from '@/core/RoleService.js';
import type { DataSource } from 'typeorm';
@Injectable()
export class NotePiningService {
@ -34,6 +35,9 @@ export class NotePiningService {
@Inject(DI.userNotePiningsRepository)
private userNotePiningsRepository: UserNotePiningsRepository,
@Inject(DI.db)
private readonly db: DataSource,
private userEntityService: UserEntityService,
private idService: IdService,
private roleService: RoleService,
@ -60,21 +64,23 @@ export class NotePiningService {
throw new IdentifiableError('70c4e51f-5bea-449c-a030-53bee3cce202', 'No such note.');
}
const pinings = await this.userNotePiningsRepository.findBy({ userId: user.id });
await this.db.transaction(async tem => {
const pinings = await tem.findBy(MiUserNotePining, { userId: user.id });
if (pinings.length >= (await this.roleService.getUserPolicies(user.id)).pinLimit) {
throw new IdentifiableError('15a018eb-58e5-4da1-93be-330fcc5e4e1a', 'You can not pin notes any more.');
}
if (pinings.length >= (await this.roleService.getUserPolicies(user.id)).pinLimit) {
throw new IdentifiableError('15a018eb-58e5-4da1-93be-330fcc5e4e1a', 'You can not pin notes any more.');
}
if (pinings.some(pining => pining.noteId === note.id)) {
throw new IdentifiableError('23f0cf4e-59a3-4276-a91d-61a5891c1514', 'That note has already been pinned.');
}
if (pinings.some(pining => pining.noteId === note.id)) {
throw new IdentifiableError('23f0cf4e-59a3-4276-a91d-61a5891c1514', 'That note has already been pinned.');
}
await this.userNotePiningsRepository.insert({
id: this.idService.gen(),
userId: user.id,
noteId: note.id,
} as MiUserNotePining);
await tem.insert(MiUserNotePining, {
id: this.idService.gen(),
userId: user.id,
noteId: note.id,
});
});
// Deliver to remote followers
if (this.userEntityService.isLocalUser(user) && !note.localOnly && ['public', 'home'].includes(note.visibility)) {