diff --git a/eventtracking/backends/event_bus.py b/eventtracking/backends/event_bus.py new file mode 100644 index 00000000..9b0f9be2 --- /dev/null +++ b/eventtracking/backends/event_bus.py @@ -0,0 +1,28 @@ +"""Event tracker backend that emits events to the event-bus.""" +from openedx_events.analytics.signals import TRACKING_EVENT_EMITTED +from openedx_events.analytics.data import TrackingLogData + +class EventBusRoutingBackend: + """ + Event tracker backend that emits an Open edX public signal. + """ + + def __init__(self, **kwargs): + """ + Event tracker backend that emits an Open edX public signal. + """ + + def send(self, event): + """ + Emit the TRACKING_EVENT_EMITTED Open edX public signal to allow + other apps to listen for tracking events. + """ + # .. event_implemented_name: TRACKING_EVENT_EMITTED + TRACKING_EVENT_EMITTED.send_event( + tracking_log=TrackingLogData( + name=event.get('name'), + timestamp=event.get('timestamp'), + data=event.get('data'), + context=event.get('context') + ) + ) diff --git a/eventtracking/backends/tests/test_event_bus.py b/eventtracking/backends/tests/test_event_bus.py new file mode 100644 index 00000000..952d8535 --- /dev/null +++ b/eventtracking/backends/tests/test_event_bus.py @@ -0,0 +1,41 @@ +""" +Test the async routing backend. +""" +from unittest import TestCase + +from unittest.mock import sentinel, patch +from eventtracking.backends.event_bus import EventBusRoutingBackend +from openedx_events.analytics.data import TrackingLogData + +class TestAsyncRoutingBackend(TestCase): + """ + Test the async routing backend. + """ + + def setUp(self): + super().setUp() + self.sample_event = { + 'name': str(sentinel.name), + 'data': 'data', + 'timestamp': '2020-01-01T12:12:12.000000+00:00', + 'context': {}, + } + + @patch('eventtracking.backends.event_bus.EventBusRoutingBackend.send') + def test_successful_send(self, mocked_send_event): + backend = EventBusRoutingBackend() + backend.send(self.sample_event) + mocked_send_event.assert_called_once_with(self.sample_event) + + @patch('eventtracking.backends.event_bus.TRACKING_EVENT_EMITTED.send_event') + def test_successful_send_event(self, mocked_send_event): + backend = EventBusRoutingBackend() + backend.send(self.sample_event) + mocked_send_event.assert_called_once_with( + tracking_log=TrackingLogData( + name=self.sample_event['name'], + timestamp=self.sample_event['timestamp'], + data=self.sample_event['data'], + context=self.sample_event['context'] + ) + ) diff --git a/requirements/base.in b/requirements/base.in index a2f491a7..055b6415 100644 --- a/requirements/base.in +++ b/requirements/base.in @@ -8,3 +8,4 @@ pytz six celery edx-django-utils +openedx_events diff --git a/requirements/base.txt b/requirements/base.txt index b00bf975..ef2be957 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -8,11 +8,15 @@ amqp==5.1.1 # via kombu asgiref==3.7.2 # via django +attrs==23.1.0 + # via openedx-events backports-zoneinfo[tzdata]==0.2.1 - # via kombu -billiard==3.6.4.0 + # via + # celery + # kombu +billiard==4.1.0 # via celery -celery==5.2.7 +celery==5.3.0 # via # -c requirements/constraints.txt # -r requirements/base.in @@ -37,16 +41,23 @@ django==3.2.19 # -r requirements/base.in # django-crum # edx-django-utils + # openedx-events django-crum==0.7.9 # via edx-django-utils django-waffle==3.0.0 # via edx-django-utils edx-django-utils==5.5.0 # via -r requirements/base.in +edx-opaque-keys[django]==2.3.0 + # via openedx-events +fastavro==1.7.4 + # via openedx-events kombu==5.3.0 # via celery newrelic==8.8.0 # via edx-django-utils +openedx-events==8.0.1 + # via -r requirements/base.in pbr==5.11.1 # via stevedore prompt-toolkit==3.0.38 @@ -56,28 +67,36 @@ psutil==5.9.5 pycparser==2.21 # via cffi pymongo==3.13.0 - # via -r requirements/base.in + # via + # -r requirements/base.in + # edx-opaque-keys pynacl==1.5.0 # via edx-django-utils +python-dateutil==2.8.2 + # via celery pytz==2023.3 # via # -r requirements/base.in - # celery # django six==1.16.0 # via # -r requirements/base.in # click-repl + # python-dateutil sqlparse==0.4.4 # via django stevedore==5.1.0 - # via edx-django-utils + # via + # edx-django-utils + # edx-opaque-keys typing-extensions==4.6.3 # via # asgiref # kombu tzdata==2023.3 - # via backports-zoneinfo + # via + # backports-zoneinfo + # celery vine==5.0.0 # via # amqp diff --git a/requirements/celery52.txt b/requirements/celery52.txt index 985a56b7..d14bfa93 100644 --- a/requirements/celery52.txt +++ b/requirements/celery52.txt @@ -1,6 +1,6 @@ amqp==5.1.1 -billiard==3.6.4.0 -celery==5.2.7 +billiard==4.1.0 +celery==5.3.0 click==8.1.3 click-didyoumean==0.3.0 click-repl==0.2.0 diff --git a/requirements/dev.txt b/requirements/dev.txt index 6ae78ffe..89c7b792 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -19,13 +19,18 @@ astroid==2.15.5 # -r requirements/test.txt # pylint # pylint-celery +attrs==23.1.0 + # via + # -r requirements/test.txt + # openedx-events babel==2.12.1 # via sphinx backports-zoneinfo[tzdata]==0.2.1 # via # -r requirements/test.txt + # celery # kombu -billiard==3.6.4.0 +billiard==4.1.0 # via # -r requirements/test.txt # celery @@ -33,7 +38,7 @@ build==0.10.0 # via # -r requirements/pip-tools.txt # pip-tools -celery==5.2.7 +celery==5.3.0 # via # -c requirements/constraints.txt # -r requirements/test.txt @@ -99,6 +104,7 @@ django==3.2.19 # -r requirements/test.txt # django-crum # edx-django-utils + # openedx-events django-crum==0.7.9 # via # -r requirements/test.txt @@ -115,10 +121,18 @@ edx-lint==5.3.4 # via # -r requirements/dev.in # -r requirements/test.txt +edx-opaque-keys[django]==2.3.0 + # via + # -r requirements/test.txt + # openedx-events exceptiongroup==1.1.1 # via # -r requirements/test.txt # pytest +fastavro==1.7.4 + # via + # -r requirements/test.txt + # openedx-events filelock==3.12.0 # via # -r requirements/ci.txt @@ -165,6 +179,8 @@ newrelic==8.8.0 # via # -r requirements/test.txt # edx-django-utils +openedx-events==8.0.1 + # via -r requirements/test.txt packaging==23.1 # via # -r requirements/ci.txt @@ -237,7 +253,9 @@ pylint-plugin-utils==0.8.2 # pylint-celery # pylint-django pymongo==3.13.0 - # via -r requirements/test.txt + # via + # -r requirements/test.txt + # edx-opaque-keys pynacl==1.5.0 # via # -r requirements/test.txt @@ -252,6 +270,10 @@ pytest==7.3.1 # pytest-cov pytest-cov==4.1.0 # via -r requirements/test.txt +python-dateutil==2.8.2 + # via + # -r requirements/test.txt + # celery python-slugify==8.0.1 # via # -r requirements/test.txt @@ -260,7 +282,6 @@ pytz==2023.3 # via # -r requirements/test.txt # babel - # celery # django pyyaml==6.0 # via @@ -274,6 +295,7 @@ six==1.16.0 # -r requirements/test.txt # click-repl # edx-lint + # python-dateutil # tox snowballstemmer==2.2.0 # via sphinx @@ -302,6 +324,7 @@ stevedore==5.1.0 # -r requirements/test.txt # code-annotations # edx-django-utils + # edx-opaque-keys text-unidecode==1.3 # via # -r requirements/test.txt @@ -340,7 +363,8 @@ tzdata==2023.3 # via # -r requirements/test.txt # backports-zoneinfo -urllib3==2.0.2 + # celery +urllib3==2.0.3 # via requests vine==5.0.0 # via diff --git a/requirements/test.txt b/requirements/test.txt index 8aa393cd..f2b874cb 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -15,9 +15,14 @@ astroid==2.15.5 # via # pylint # pylint-celery +attrs==23.1.0 + # via + # -r requirements/base.txt + # openedx-events backports-zoneinfo[tzdata]==0.2.1 # via # -r requirements/base.txt + # celery # kombu # via # -r requirements/base.txt @@ -64,6 +69,7 @@ dill==0.3.6 # -r requirements/base.txt # django-crum # edx-django-utils + # openedx-events django-crum==0.7.9 # via # -r requirements/base.txt @@ -76,8 +82,16 @@ edx-django-utils==5.5.0 # via -r requirements/base.txt edx-lint==5.3.4 # via -r requirements/test.in +edx-opaque-keys[django]==2.3.0 + # via + # -r requirements/base.txt + # openedx-events exceptiongroup==1.1.1 # via pytest +fastavro==1.7.4 + # via + # -r requirements/base.txt + # openedx-events iniconfig==2.0.0 # via pytest isort==5.12.0 @@ -99,6 +113,8 @@ newrelic==8.8.0 # via # -r requirements/base.txt # edx-django-utils +openedx-events==8.0.1 + # via -r requirements/base.txt packaging==23.1 # via pytest pbr==5.11.1 @@ -137,7 +153,9 @@ pylint-plugin-utils==0.8.2 # pylint-celery # pylint-django pymongo==3.13.0 - # via -r requirements/base.txt + # via + # -r requirements/base.txt + # edx-opaque-keys pynacl==1.5.0 # via # -r requirements/base.txt @@ -146,12 +164,15 @@ pytest==7.3.1 # via pytest-cov pytest-cov==4.1.0 # via -r requirements/test.in +python-dateutil==2.8.2 + # via + # -r requirements/base.txt + # celery python-slugify==8.0.1 # via code-annotations pytz==2023.3 # via # -r requirements/base.txt - # celery # django pyyaml==6.0 # via code-annotations @@ -160,6 +181,7 @@ six==1.16.0 # -r requirements/base.txt # click-repl # edx-lint + # python-dateutil sqlparse==0.4.4 # via # -r requirements/base.txt @@ -169,6 +191,7 @@ stevedore==5.1.0 # -r requirements/base.txt # code-annotations # edx-django-utils + # edx-opaque-keys text-unidecode==1.3 # via python-slugify tomli==2.0.1 @@ -189,6 +212,7 @@ tzdata==2023.3 # via # -r requirements/base.txt # backports-zoneinfo + # celery # via # -r requirements/base.txt # amqp