Skip to content

Commit db1da28

Browse files
authored
feat: Add bulk notifications (#76)
* feat: Add bulk notifications
1 parent 527060e commit db1da28

File tree

3 files changed

+83
-3
lines changed

3 files changed

+83
-3
lines changed

docs/usage.rst

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,34 @@ and decide how each individual notification should be sent
6464
You must inherit from the base class and specify the ``name`` property for the channel to be properly registered
6565

6666

67+
Bulk sending
68+
------------
69+
70+
You can send bulk notifications by setting the ``bulk`` property to ``True`` in the context dictionary::
71+
72+
console_notification = ConsoleNotificationChannel(
73+
notification: Notification, context={'bulk': True, 'arbitrary_data': 'data'}
74+
)
75+
console_notification.notify()
76+
77+
or::
78+
79+
notify(
80+
...,
81+
extra_data={
82+
'context': {
83+
'bulk': True,
84+
}
85+
}
86+
)
87+
88+
.. note::
89+
The provider takes care of sending the payload in the most efficient way.
90+
(Some providers like ``pusher`` have a bulk api for delivering multiple notifications in a single batch).
91+
92+
6793
Notification Model
68-
-------------------
94+
-----------------
6995

7096
Django notifs includes an inbuilt notification model with the following fields:
7197

notifications/backends/base.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,16 @@ def get_notification_provider(provider_path, context):
2222
@classmethod
2323
def consume(cls, provider, provider_class, payload, context):
2424
notification_channel = cls.get_notification_provider(provider_class, context)
25-
notification_channel.send(payload)
25+
26+
bulk = context.get('bulk', False)
27+
if bulk is True:
28+
notification_channel.send_bulk(payload)
29+
else:
30+
notification_channel.send(payload)
31+
2632
cls.logger.info(
27-
'Sent notification with the %s channel. context: %s\n' % (provider, context)
33+
'Sent notification with the %s provider with context: %s\n'
34+
% (provider, context)
2835
)
2936

3037
@abc.abstractclassmethod

notifications/tests/test_general.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""General Tests."""
22

33
import time
4+
from unittest import mock
45

56
from django.db import models
67
from django.contrib.auth import get_user_model
@@ -10,6 +11,7 @@
1011
from .. import NotificationError
1112
from ..models import BaseNotificationModel
1213
from ..backends.base import BaseBackend
14+
from ..channels import ConsoleNotificationChannel
1315

1416

1517
Notification = get_notification_model()
@@ -123,6 +125,51 @@ def test_silent_notification(self):
123125

124126
self.assertEqual(notifications.count(), 0)
125127

128+
@mock.patch('notifications.providers.ConsoleNotificationProvider.send_bulk')
129+
def test_bulk_notification_notify(self, send_bulk):
130+
notify(
131+
source=self.user2,
132+
source_display_name='User 2',
133+
recipient=self.user1,
134+
action='Notified',
135+
category='Silent notification',
136+
obj=self.user2,
137+
url='http://example.com',
138+
short_description='Short Description',
139+
is_read=False,
140+
channels=('console',),
141+
extra_data={
142+
'context': {
143+
'bulk': True,
144+
}
145+
},
146+
)
147+
148+
send_bulk.assert_called_once_with(
149+
{'context': {'bulk': True}, 'payload': 'console'}
150+
)
151+
152+
@mock.patch('notifications.providers.ConsoleNotificationProvider.send_bulk')
153+
def test_bulk_notification_direct(self, send_bulk):
154+
notification = Notification.objects.create(
155+
source=self.user2,
156+
source_display_name='User 2',
157+
recipient=self.user1,
158+
action='Notified',
159+
category='Silent notification',
160+
obj=self.user2,
161+
url='http://example.com',
162+
short_description='Short Description',
163+
is_read=False,
164+
)
165+
console_notification = ConsoleNotificationChannel(
166+
notification, context={'bulk': True}
167+
)
168+
payload = console_notification.build_payload('console')
169+
console_notification.notify()
170+
171+
send_bulk.assert_called_once_with(payload)
172+
126173
def test_notify_invalid_channel(self):
127174
"""An invalid channel should raise a AttributeError."""
128175
notification_kwargs = dict(

0 commit comments

Comments
 (0)