Skip to content

[Chat] Implement Celery for Asynchronous Notifications in Django Channels #86

Description

@mehalyna
  1. Define a Celery Task for Notifications

    • Create a task that sends notifications asynchronously through Django Channels.

    • Steps:

      • In your app (e.g., notifications/), locate tasks.py. If it doesn’t exist, create it.
      • Define a Celery task to handle the notification broadcasting logic.
      # notifications/tasks.py
      from celery import shared_task
      from channels.layers import get_channel_layer
      from asgiref.sync import async_to_sync
      import json
      
      @shared_task
      def send_notification_task(room_id, notification_data):
          """
          Celery task to send a notification message to the specified room.
          Args:
              room_id (str): The room ID where the notification should be sent.
              notification_data (dict): Data to be included in the notification.
          """
          channel_layer = get_channel_layer()
          async_to_sync(channel_layer.group_send)(
              f"chat_{room_id}",
              {
                  "type": "send_notification",
                  "notification": notification_data,
              }
          )
  2. Update Django Signal to Use Celery Task

    • Replace the direct async_to_sync call in your signal with a Celery task to avoid blocking.

    • Steps:

      • Go to your signals.py where notifications are sent when a new message is created.
      • Import the send_notification_task from tasks.py.
      • Modify the signal to call send_notification_task.delay() instead of using async_to_sync.
      # notifications/signals.py
      from django.db.models.signals import post_save
      from django.dispatch import receiver
      from .models import Message
      from .tasks import send_notification_task
      
      @receiver(post_save, sender=Message)
      def send_notification_via_channels(sender, instance, created, **kwargs):
          if created:
              room_id = instance.room.id
              notification_data = {
                  "user": instance.receiver.username,
                  "message": instance.message,
                  "is_read": False,
              }
              # Offload the notification to Celery task
              send_notification_task.delay(room_id, notification_data)
  3. Set Up and Run the Celery Worker

    • Ensure Celery is running to pick up and execute tasks.
    • Steps:
      • Start your Celery worker using the following command:
        celery -A project_name worker -l info
      • Make sure Redis or your chosen message broker is running (e.g., Redis on redis://localhost:6379/0).
      • Check for any errors in the console output to ensure Celery is processing tasks correctly.
  4. Test the Notification System

    • Verify that notifications are sent asynchronously through Celery.
    • Steps:
      • Create a test message in your application to trigger the signal.
      • Observe the console or logs where Celery is running to confirm that the send_notification_task task is received and executed.
      • Check your frontend to confirm that the notification is displayed correctly.
  5. Monitor and Optimize Celery

    • Ensure Celery is performing efficiently and identify potential bottlenecks.
    • Steps:
      • Use Celery’s Flower or Prometheus integration for task monitoring if desired.
      • Adjust the concurrency and prefetch settings of Celery workers as needed to optimize performance based on system load.

#115

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions