Skip to content

Commit 4190e65

Browse files
pablohashescobarlifeiscontent
authored andcommitted
fix: error handling for db based integrity errors (#6632)
* fix: error handling for db based integrity errors * fix: meta endpoint to return correct error message * fix: module activity
1 parent 4552c0a commit 4190e65

File tree

9 files changed

+250
-167
lines changed

9 files changed

+250
-167
lines changed

apiserver/plane/api/serializers/issue.py

Lines changed: 79 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Django imports
22
from django.utils import timezone
33
from lxml import html
4+
from django.db import IntegrityError
45

56
# Third party imports
67
from rest_framework import serializers
@@ -138,47 +139,56 @@ def create(self, validated_data):
138139
updated_by_id = issue.updated_by_id
139140

140141
if assignees is not None and len(assignees):
141-
IssueAssignee.objects.bulk_create(
142-
[
143-
IssueAssignee(
144-
assignee_id=assignee_id,
142+
try:
143+
IssueAssignee.objects.bulk_create(
144+
[
145+
IssueAssignee(
146+
assignee_id=assignee_id,
147+
issue=issue,
148+
project_id=project_id,
149+
workspace_id=workspace_id,
150+
created_by_id=created_by_id,
151+
updated_by_id=updated_by_id,
152+
)
153+
for assignee_id in assignees
154+
],
155+
batch_size=10,
156+
)
157+
except IntegrityError:
158+
pass
159+
else:
160+
try:
161+
# Then assign it to default assignee
162+
if default_assignee_id is not None:
163+
IssueAssignee.objects.create(
164+
assignee_id=default_assignee_id,
145165
issue=issue,
146166
project_id=project_id,
147167
workspace_id=workspace_id,
148168
created_by_id=created_by_id,
149169
updated_by_id=updated_by_id,
150170
)
151-
for assignee_id in assignees
152-
],
153-
batch_size=10,
154-
)
155-
else:
156-
# Then assign it to default assignee
157-
if default_assignee_id is not None:
158-
IssueAssignee.objects.create(
159-
assignee_id=default_assignee_id,
160-
issue=issue,
161-
project_id=project_id,
162-
workspace_id=workspace_id,
163-
created_by_id=created_by_id,
164-
updated_by_id=updated_by_id,
165-
)
171+
except IntegrityError:
172+
pass
166173

167174
if labels is not None and len(labels):
168-
IssueLabel.objects.bulk_create(
169-
[
170-
IssueLabel(
171-
label_id=label_id,
172-
issue=issue,
173-
project_id=project_id,
174-
workspace_id=workspace_id,
175-
created_by_id=created_by_id,
176-
updated_by_id=updated_by_id,
177-
)
178-
for label_id in labels
179-
],
180-
batch_size=10,
181-
)
175+
try:
176+
IssueLabel.objects.bulk_create(
177+
[
178+
IssueLabel(
179+
label_id=label_id,
180+
issue=issue,
181+
project_id=project_id,
182+
workspace_id=workspace_id,
183+
created_by_id=created_by_id,
184+
updated_by_id=updated_by_id,
185+
)
186+
for label_id in labels
187+
],
188+
batch_size=10,
189+
)
190+
except IntegrityError:
191+
pass
182192

183193
return issue
184194

@@ -194,39 +204,45 @@ def update(self, instance, validated_data):
194204

195205
if assignees is not None:
196206
IssueAssignee.objects.filter(issue=instance).delete()
197-
IssueAssignee.objects.bulk_create(
198-
[
199-
IssueAssignee(
200-
assignee_id=assignee_id,
201-
issue=instance,
202-
project_id=project_id,
203-
workspace_id=workspace_id,
204-
created_by_id=created_by_id,
205-
updated_by_id=updated_by_id,
206-
)
207-
for assignee_id in assignees
208-
],
209-
batch_size=10,
210-
ignore_conflicts=True,
211-
)
207+
try:
208+
IssueAssignee.objects.bulk_create(
209+
[
210+
IssueAssignee(
211+
assignee_id=assignee_id,
212+
issue=instance,
213+
project_id=project_id,
214+
workspace_id=workspace_id,
215+
created_by_id=created_by_id,
216+
updated_by_id=updated_by_id,
217+
)
218+
for assignee_id in assignees
219+
],
220+
batch_size=10,
221+
ignore_conflicts=True,
222+
)
223+
except IntegrityError:
224+
pass
212225

213226
if labels is not None:
214227
IssueLabel.objects.filter(issue=instance).delete()
215-
IssueLabel.objects.bulk_create(
216-
[
217-
IssueLabel(
218-
label_id=label_id,
219-
issue=instance,
220-
project_id=project_id,
221-
workspace_id=workspace_id,
222-
created_by_id=created_by_id,
223-
updated_by_id=updated_by_id,
224-
)
225-
for label_id in labels
226-
],
227-
batch_size=10,
228-
ignore_conflicts=True,
229-
)
228+
try:
229+
IssueLabel.objects.bulk_create(
230+
[
231+
IssueLabel(
232+
label_id=label_id,
233+
issue=instance,
234+
project_id=project_id,
235+
workspace_id=workspace_id,
236+
created_by_id=created_by_id,
237+
updated_by_id=updated_by_id,
238+
)
239+
for label_id in labels
240+
],
241+
batch_size=10,
242+
ignore_conflicts=True,
243+
)
244+
except IntegrityError:
245+
pass
230246

231247
# Time updation occues even when other related models are updated
232248
instance.updated_at = timezone.now()

apiserver/plane/app/serializers/issue.py

Lines changed: 78 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from django.utils import timezone
33
from django.core.validators import URLValidator
44
from django.core.exceptions import ValidationError
5+
from django.db import IntegrityError
56

67
# Third Party imports
78
from rest_framework import serializers
@@ -134,47 +135,56 @@ def create(self, validated_data):
134135
updated_by_id = issue.updated_by_id
135136

136137
if assignees is not None and len(assignees):
137-
IssueAssignee.objects.bulk_create(
138-
[
139-
IssueAssignee(
140-
assignee=user,
141-
issue=issue,
142-
project_id=project_id,
143-
workspace_id=workspace_id,
144-
created_by_id=created_by_id,
145-
updated_by_id=updated_by_id,
146-
)
147-
for user in assignees
148-
],
149-
batch_size=10,
150-
)
138+
try:
139+
IssueAssignee.objects.bulk_create(
140+
[
141+
IssueAssignee(
142+
assignee=user,
143+
issue=issue,
144+
project_id=project_id,
145+
workspace_id=workspace_id,
146+
created_by_id=created_by_id,
147+
updated_by_id=updated_by_id,
148+
)
149+
for user in assignees
150+
],
151+
batch_size=10,
152+
)
153+
except IntegrityError:
154+
pass
151155
else:
152156
# Then assign it to default assignee
153157
if default_assignee_id is not None:
154-
IssueAssignee.objects.create(
155-
assignee_id=default_assignee_id,
156-
issue=issue,
157-
project_id=project_id,
158-
workspace_id=workspace_id,
159-
created_by_id=created_by_id,
160-
updated_by_id=updated_by_id,
161-
)
162-
163-
if labels is not None and len(labels):
164-
IssueLabel.objects.bulk_create(
165-
[
166-
IssueLabel(
167-
label=label,
158+
try:
159+
IssueAssignee.objects.create(
160+
assignee_id=default_assignee_id,
168161
issue=issue,
169162
project_id=project_id,
170163
workspace_id=workspace_id,
171164
created_by_id=created_by_id,
172165
updated_by_id=updated_by_id,
173166
)
174-
for label in labels
175-
],
176-
batch_size=10,
177-
)
167+
except IntegrityError:
168+
pass
169+
170+
if labels is not None and len(labels):
171+
try:
172+
IssueLabel.objects.bulk_create(
173+
[
174+
IssueLabel(
175+
label=label,
176+
issue=issue,
177+
project_id=project_id,
178+
workspace_id=workspace_id,
179+
created_by_id=created_by_id,
180+
updated_by_id=updated_by_id,
181+
)
182+
for label in labels
183+
],
184+
batch_size=10,
185+
)
186+
except IntegrityError:
187+
pass
178188

179189
return issue
180190

@@ -190,39 +200,45 @@ def update(self, instance, validated_data):
190200

191201
if assignees is not None:
192202
IssueAssignee.objects.filter(issue=instance).delete()
193-
IssueAssignee.objects.bulk_create(
194-
[
195-
IssueAssignee(
196-
assignee=user,
197-
issue=instance,
198-
project_id=project_id,
199-
workspace_id=workspace_id,
200-
created_by_id=created_by_id,
201-
updated_by_id=updated_by_id,
202-
)
203-
for user in assignees
204-
],
205-
batch_size=10,
206-
ignore_conflicts=True,
207-
)
203+
try:
204+
IssueAssignee.objects.bulk_create(
205+
[
206+
IssueAssignee(
207+
assignee=user,
208+
issue=instance,
209+
project_id=project_id,
210+
workspace_id=workspace_id,
211+
created_by_id=created_by_id,
212+
updated_by_id=updated_by_id,
213+
)
214+
for user in assignees
215+
],
216+
batch_size=10,
217+
ignore_conflicts=True,
218+
)
219+
except IntegrityError:
220+
pass
208221

209222
if labels is not None:
210223
IssueLabel.objects.filter(issue=instance).delete()
211-
IssueLabel.objects.bulk_create(
212-
[
213-
IssueLabel(
214-
label=label,
215-
issue=instance,
216-
project_id=project_id,
217-
workspace_id=workspace_id,
218-
created_by_id=created_by_id,
219-
updated_by_id=updated_by_id,
220-
)
221-
for label in labels
222-
],
223-
batch_size=10,
224-
ignore_conflicts=True,
225-
)
224+
try:
225+
IssueLabel.objects.bulk_create(
226+
[
227+
IssueLabel(
228+
label=label,
229+
issue=instance,
230+
project_id=project_id,
231+
workspace_id=workspace_id,
232+
created_by_id=created_by_id,
233+
updated_by_id=updated_by_id,
234+
)
235+
for label in labels
236+
],
237+
batch_size=10,
238+
ignore_conflicts=True,
239+
)
240+
except IntegrityError:
241+
pass
226242

227243
# Time updation occues even when other related models are updated
228244
instance.updated_at = timezone.now()

apiserver/plane/app/views/asset/v2.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from django.conf import settings
66
from django.http import HttpResponseRedirect
77
from django.utils import timezone
8+
from django.db import IntegrityError
89

910
# Third party imports
1011
from rest_framework import status
@@ -679,15 +680,30 @@ def post(self, request, slug, project_id, entity_id):
679680
[self.save_project_cover(asset, project_id) for asset in assets]
680681

681682
if asset.entity_type == FileAsset.EntityTypeContext.ISSUE_DESCRIPTION:
682-
assets.update(issue_id=entity_id)
683+
# For some cases, the bulk api is called after the issue is deleted creating
684+
# an integrity error
685+
try:
686+
assets.update(issue_id=entity_id)
687+
except IntegrityError:
688+
pass
683689

684690
if asset.entity_type == FileAsset.EntityTypeContext.COMMENT_DESCRIPTION:
685-
assets.update(comment_id=entity_id)
691+
# For some cases, the bulk api is called after the comment is deleted
692+
# creating an integrity error
693+
try:
694+
assets.update(comment_id=entity_id)
695+
except IntegrityError:
696+
pass
686697

687698
if asset.entity_type == FileAsset.EntityTypeContext.PAGE_DESCRIPTION:
688699
assets.update(page_id=entity_id)
689700

690701
if asset.entity_type == FileAsset.EntityTypeContext.DRAFT_ISSUE_DESCRIPTION:
691-
assets.update(draft_issue_id=entity_id)
702+
# For some cases, the bulk api is called after the draft issue is deleted
703+
# creating an integrity error
704+
try:
705+
assets.update(draft_issue_id=entity_id)
706+
except IntegrityError:
707+
pass
692708

693709
return Response(status=status.HTTP_204_NO_CONTENT)

0 commit comments

Comments
 (0)