Coverage for src/expo_notifications/tasks/check_receipts_task.py: 100%

1 from celery import shared_task

2 from django.utils import timezone

3 from exponent_server_sdk import (

4 DeviceNotRegisteredError,

5 PushClient,

6 PushReceipt,

7 PushServerError,

8 PushTicketError,

9)

10 from requests.exceptions import ConnectionError, HTTPError

11

12 from expo_notifications.conf import settings

13 from expo_notifications.models import Receipt, Ticket

14 from expo_notifications.tasks.session import session

15

16

17@shared_task(

18 bind=True,

19 ignore_result=True,

20 max_retries=settings.checking_task_max_retries,

21 default_retry_delay=settings.checking_task_retry_delay.total_seconds(),

22)

23 def check_receipts(self, ticket_pks: list[str]) -> None:

24 tickets = Ticket.objects.filter(pk__in=ticket_pks).exclude(external_id="")

25

26 push_tickets = [ticket.to_push_ticket() for ticket in tickets]

27

28 push_client = PushClient(session=session)

29

30 try:

31 push_receipts: list[PushReceipt] = push_client.check_receipts_multiple(

32 push_tickets

33 )

34 except PushServerError:

35 raise self.retry()

36 except (ConnectionError, HTTPError):

37 raise self.retry()

38

39 receipts: list[Receipt] = []

40

41 for push_receipt in push_receipts:

42 ticket = tickets.get(external_id=push_receipt.id)

43

44 try:

45 push_receipt.validate_response()

46 except DeviceNotRegisteredError:

47 ticket.message.device.is_active = False

48 ticket.message.device.save()

49 except PushTicketError:

50 pass

51

52 receipts.append(

53 Receipt(

54 ticket=ticket,

55 is_success=push_receipt.is_success(),

56 error_message=push_receipt.message,

57 date_checked=timezone.now(),

58 )

59 )

60

61 Receipt.objects.bulk_create(receipts)