diff --git a/app/celery/tasks.py b/app/celery/tasks.py index 1f130f42d..1adc449ee 100644 --- a/app/celery/tasks.py +++ b/app/celery/tasks.py @@ -73,7 +73,6 @@ def process_job(job_id): def process_row(row_number, recipient, personalisation, template, job, service): template_type = template.template_type - encrypted = encryption.encrypt({ 'template': str(template.id), 'template_version': job.template_version, @@ -86,20 +85,24 @@ def process_row(row_number, recipient, personalisation, template, job, service): send_fns = { SMS_TYPE: send_sms, EMAIL_TYPE: send_email, + LETTER_TYPE: persist_letter } queues = { SMS_TYPE: 'db-sms', EMAIL_TYPE: 'db-email', + LETTER_TYPE: 'db-letter', } send_fn = send_fns[template_type] - send_fn.apply_async(( - str(job.service_id), - create_uuid(), - encrypted, - datetime.utcnow().strftime(DATETIME_FORMAT)), + send_fn.apply_async( + ( + str(service.id), + create_uuid(), + encrypted, + datetime.utcnow().strftime(DATETIME_FORMAT) + ), queue=queues[template_type] if not service.research_mode else 'research-mode' ) @@ -207,6 +210,40 @@ def send_email(self, handle_exception(self, notification, notification_id, e) +@notify_celery.task(bind=True, name="persist-letter", max_retries=5, default_retry_delay=300) +@statsd(namespace="tasks") +def persist_letter( + self, + service_id, + notification_id, + encrypted_notification, + created_at +): + notification = encryption.decrypt(encrypted_notification) + service = dao_fetch_service_by_id(service_id) + try: + saved_notification = persist_notification( + template_id=notification['template'], + template_version=notification['template_version'], + recipient=notification['to'], + service=service, + personalisation=notification.get('personalisation'), + notification_type=EMAIL_TYPE, + api_key_id=None, + key_type=KEY_TYPE_NORMAL, + created_at=created_at, + job_id=notification.get('job', None), + job_row_number=notification.get('row_number', None), + notification_id=notification_id + ) + + # TODO: deliver letters + + current_app.logger.info("Letter {} created at {}".format(saved_notification.id, created_at)) + except SQLAlchemyError as e: + handle_exception(self, notification, notification_id, e) + + def handle_exception(task, notification, notification_id, exc): if not get_notification_by_id(notification_id): retry_msg = '{task} notification for job {job} row number {row} and notification id {noti}'.format( diff --git a/tests/app/celery/test_tasks.py b/tests/app/celery/test_tasks.py index 78235001a..66ad2f256 100644 --- a/tests/app/celery/test_tasks.py +++ b/tests/app/celery/test_tasks.py @@ -1,6 +1,6 @@ import uuid from datetime import datetime -from unittest.mock import Mock +from unittest.mock import Mock, ANY import pytest from freezegun import freeze_time @@ -289,6 +289,44 @@ def test_should_process_all_sms_job(sample_job, # -------------- process_row tests -------------- # + +@freeze_time('2001-01-01T12:00:00') +@pytest.mark.parametrize('template_type, research_mode, expected_function, expected_queue', [ + (SMS_TYPE, False, 'send_sms', 'db-sms'), + (SMS_TYPE, True, 'send_sms', 'research-mode'), + (EMAIL_TYPE, False, 'send_email', 'db-email'), + (EMAIL_TYPE, True, 'send_email', 'research-mode'), + (LETTER_TYPE, False, 'persist_letter', 'db-letter'), + (LETTER_TYPE, True, 'persist_letter', 'research-mode'), +]) +def test_process_row_sends_letter_task(template_type, research_mode, expected_function, expected_queue, mocker): + mocker.patch('app.celery.tasks.create_uuid', return_value='noti_uuid') + task_mock = mocker.patch('app.celery.tasks.{}.apply_async'.format(expected_function)) + encrypt_mock = mocker.patch('app.celery.tasks.encryption.encrypt') + template = Mock(id='template_id', template_type=template_type) + job = Mock(id='job_id', template_version='temp_vers') + service = Mock(id='service_id', research_mode=research_mode) + + process_row('row_num', 'recip', {'foo': 'bar'}, template, job, service) + + encrypt_mock.assert_called_once_with({ + 'template': 'template_id', + 'template_version': 'temp_vers', + 'job': 'job_id', + 'to': 'recip', + 'row_number': 'row_num', + 'personalisation': {'foo': 'bar'} + }) + task_mock.assert_called_once_with( + ( + 'service_id', + 'noti_uuid', + # encrypted data + encrypt_mock.return_value, + '2001-01-01T12:00:00.000000Z' + ), + queue=expected_queue + ) # -------- send_sms and send_email tests -------- #