Coverage for expo_notifications/tasks/send_messages_task.py: 31%

1 from celery import shared_task

2 from django.utils import timezone

3 from exponent_server_sdk import (

4 DeviceNotRegisteredError,

5 PushClient,

6 PushServerError,

7 PushTicket,

8 PushTicketError,

9)

10 from requests.exceptions import ConnectionError, HTTPError

11

12 from expo_notifications.conf import settings

13 from expo_notifications.models import Message, Ticket

14 from expo_notifications.tasks import check_receipts

15 from expo_notifications.tasks.session import session

16

17

18@shared_task(

19 bind=True,

20 ignore_result=True,

21 max_retries=settings.sending_task_max_retries,

22 default_retry_delay=settings.sending_task_retry_delay.total_seconds(),

23)

24 def send_messages(self, message_pks: list[str]) -> None:

25 messages = Message.objects.filter(pk__in=message_pks, device__is_active=True)

26

27 push_messages = [message.to_push_message() for message in messages]

28

29 push_client = PushClient(session=session)

30

31 try:

32 push_tickets: list[PushTicket] = push_client.publish_multiple(push_messages)

33 except PushServerError:

34 raise self.retry()

35 except (ConnectionError, HTTPError):

36 raise self.retry()

37

38 tickets: list[Ticket] = []

39

40 for message, push_ticket in zip(messages, push_tickets):

41 try:

42 push_ticket.validate_response()

43 except DeviceNotRegisteredError:

44 message.device.is_active = False

45 message.device.save()

46 except PushTicketError:

47 pass

48

49 tickets.append(

50 Ticket(

51 message=message,

52 is_success=push_ticket.is_success(),

53 external_id=push_ticket.id,

54 error_message=push_ticket.message,

55 date_received=timezone.now(),

56 )

57 )

58

59 pks_of_success_tickets = [

60 ticket.pk for ticket in Ticket.objects.bulk_create(tickets) if ticket.is_success

61 ]

62

63 if pks_of_success_tickets:

64 check_receipts.apply_async(

65 kwargs={"ticket_pks": pks_of_success_tickets},

66 countdown=settings.receipt_check_delay.total_seconds(),

67 )