diff --git a/chats/apps/api/v1/rooms/viewsets.py b/chats/apps/api/v1/rooms/viewsets.py index 38824666..69722722 100644 --- a/chats/apps/api/v1/rooms/viewsets.py +++ b/chats/apps/api/v1/rooms/viewsets.py @@ -1,8 +1,7 @@ -import time from datetime import timedelta from django.conf import settings -from django.db import DatabaseError, transaction +from django.db import transaction from django.db.models import BooleanField, Case, Count, Max, OuterRef, Q, Subquery, When from django.utils import timezone from django_filters.rest_framework import DjangoFilterBackend @@ -141,6 +140,7 @@ def bulk_update_msgs(self, request, *args, **kwargs): status=status.HTTP_200_OK, ) + @transaction.atomic @action(detail=True, methods=["PUT", "PATCH"], url_name="close") def close( self, request, *args, **kwargs @@ -151,31 +151,17 @@ def close( # Add send room notification to the channels group instance = self.get_object() - for attempt in range(settings.MAX_RETRIES): - try: - with transaction.atomic(): - tags = request.data.get("tags", None) - instance.close(tags, "agent") - serialized_data = RoomSerializer(instance=instance) - instance.notify_queue("close", callback=True) - instance.notify_user("close") - - if not settings.ACTIVATE_CALC_METRICS: - return Response(serialized_data.data, status=status.HTTP_200_OK) - - close_room(str(instance.pk)) - return Response(serialized_data.data, status=status.HTTP_200_OK) - - except DatabaseError as error: - if attempt < settings.MAX_RETRIES - 1: - delay = settings.RETRY_DELAY_SECONDS * (2**attempt) - time.sleep(delay) - continue - else: - return Response( - {"error": f"Transaction failed after retries: {str(error)}"}, - status=status.HTTP_500_INTERNAL_SERVER_ERROR, - ) + tags = request.data.get("tags", None) + instance.close(tags, "agent") + serialized_data = RoomSerializer(instance=instance) + instance.notify_queue("close", callback=True) + instance.notify_user("close") + + if not settings.ACTIVATE_CALC_METRICS: + return Response(serialized_data.data, status=status.HTTP_200_OK) + + close_room(str(instance.pk)) + return Response(serialized_data.data, status=status.HTTP_200_OK) def perform_create(self, serializer): serializer.save() diff --git a/chats/apps/rooms/models.py b/chats/apps/rooms/models.py index 63b87e7f..7fc5887d 100644 --- a/chats/apps/rooms/models.py +++ b/chats/apps/rooms/models.py @@ -1,7 +1,10 @@ import json +import time from datetime import timedelta import requests +import sentry_sdk +from django.conf import settings from django.core.exceptions import ObjectDoesNotExist from django.core.serializers.json import DjangoJSONEncoder from django.db import models @@ -180,23 +183,35 @@ def request_callback(self, room_data: dict): if self.callback_url is None: return None - try: - response = requests.post( - self.callback_url, - data=json.dumps( - {"type": "room.update", "content": room_data}, - sort_keys=True, - indent=1, - cls=DjangoJSONEncoder, - ), - headers={"content-type": "application/json"}, - ) - response.raise_for_status() - - except RequestException as error: - raise RuntimeError( - f"Failed to send callback to {self.callback_url}: {str(error)}" - ) + for attempt in range(settings.MAX_RETRIES): + try: + response = requests.post( + self.callback_url, + data=json.dumps( + {"type": "room.update", "content": room_data}, + sort_keys=True, + indent=1, + cls=DjangoJSONEncoder, + ), + headers={"content-type": "application/json"}, + ) + + if response.status_code == 404: + sentry_sdk.capture_message( + f"Callback returned 404 ERROR for URL: {self.callback_url}" + ) + return None + else: + response.raise_for_status() + + except RequestException: + if attempt < settings.MAX_RETRIES - 1: + delay = settings.RETRY_DELAY_SECONDS * (2**attempt) + time.sleep(delay) + else: + raise RuntimeError( + f"Failed to send callback to {self.callback_url}" + ) def base_notification(self, content, action): if self.user: