Skip to content

Commit

Permalink
Handle partial failure
Browse files Browse the repository at this point in the history
  • Loading branch information
sravfeyn committed Aug 2, 2024
1 parent e1c03fd commit c59a387
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 9 deletions.
24 changes: 18 additions & 6 deletions commcare_connect/events/tests.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from datetime import datetime

from rest_framework.test import APIClient

from commcare_connect.opportunity.models import Opportunity
Expand All @@ -8,34 +10,44 @@

def test_post_events(mobile_user_with_connect_link: User, api_client: APIClient, opportunity: Opportunity):
api_client.force_authenticate(mobile_user_with_connect_link)
assert Event.objects.count() == 0
response = api_client.post(
"/api/events/",
data=[
{
"event_type": "invalid_event_name",
"event_type": Event.Type.INVITE_SENT,
"user": mobile_user_with_connect_link.pk,
"opportunity": opportunity.pk,
"date_created": datetime.utcnow(),
},
{
"event_type": Event.Type.RECORDS_APPROVED,
"user": mobile_user_with_connect_link.pk,
"opportunity": opportunity.pk,
}
"date_created": datetime.utcnow(),
},
],
format="json",
)
assert response.status_code == 400
assert Event.objects.count() == 0
assert response.status_code == 201
assert Event.objects.count() == 2
response = api_client.post(
"/api/events/",
data=[
{
"event_type": Event.Type.INVITE_SENT,
"user": mobile_user_with_connect_link.pk,
"user": -1,
"opportunity": opportunity.pk,
"date_created": datetime.utcnow(),
},
{
"event_type": Event.Type.RECORDS_APPROVED,
"user": mobile_user_with_connect_link.pk,
"opportunity": opportunity.pk,
"date_created": datetime.utcnow(),
},
],
format="json",
)
assert response.status_code == 201
assert response.status_code == 400
assert Event.objects.count() == 2
22 changes: 19 additions & 3 deletions commcare_connect/events/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import django_tables2 as tables
from dal.autocomplete import ModelSelect2
from django.db import transaction
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
from django_filters import ChoiceFilter, FilterSet, ModelChoiceFilter
Expand Down Expand Up @@ -34,9 +35,24 @@ def create(self, request, *args, **kwargs):

serializer = self.get_serializer(data=request.data, many=True)
serializer.is_valid(raise_exception=True)

event_objects = [Event(**item) for item in serializer.validated_data]
Event.objects.bulk_create(event_objects)
try:
event_objects = [Event(**item) for item in serializer.validated_data]
Event.objects.bulk_create(event_objects)
except Exception as e:
# Bulk create failed, try saving each item individually
failed_items = []

for item in serializer.validated_data:
try:
with transaction.atomic():
Event.objects.save(**item)
except Exception:
failed_items.append((item, e))

if failed_items:
partial_error_response = {"error": "Some items could not be saved", "failed_items": failed_items}
headers = self.get_success_headers(serializer.data)
return Response(partial_error_response, status=status.HTTP_206_PARTIAL_CONTENT, headers=headers)

headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
Expand Down

0 comments on commit c59a387

Please sign in to comment.