summaryrefslogtreecommitdiff
path: root/packages/backend/src/core
diff options
context:
space:
mode:
authorMarie <github@yuugi.dev>2025-05-12 10:30:44 +0000
committerMarie <github@yuugi.dev>2025-05-12 10:30:44 +0000
commit4430c12e0e4b427982db5e2d8a87f51d70c6645a (patch)
tree70e3b712f9c292df36ccba07ddf6f9b7de71e1bd /packages/backend/src/core
parentmerge: Fix circular dependency in following feed (!1013) (diff)
parentuse transaction to avoid unique constraint error when processing duplicate Ad... (diff)
downloadsharkey-4430c12e0e4b427982db5e2d8a87f51d70c6645a.tar.gz
sharkey-4430c12e0e4b427982db5e2d8a87f51d70c6645a.tar.bz2
sharkey-4430c12e0e4b427982db5e2d8a87f51d70c6645a.zip
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>
Diffstat (limited to 'packages/backend/src/core')
-rw-r--r--packages/backend/src/core/NotePiningService.ts32
1 files changed, 19 insertions, 13 deletions
diff --git a/packages/backend/src/core/NotePiningService.ts b/packages/backend/src/core/NotePiningService.ts
index 6ab7268254..86f1a62d4a 100644
--- a/packages/backend/src/core/NotePiningService.ts
+++ b/packages/backend/src/core/NotePiningService.ts
@@ -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)) {