mirror of
https://github.com/GSA/notifications-api.git
synced 2026-09-04 16:48:26 -04:00
Refactoring the send to provider code out of the tasks folder
- building a rest endpoint to call that code to compliment the existing task based approach.
This commit is contained in:
@@ -31,6 +31,47 @@ def retry_iteration_to_delay(retry=0):
|
|||||||
return delays.get(retry, 10)
|
return delays.get(retry, 10)
|
||||||
|
|
||||||
|
|
||||||
|
@notify_celery.task(bind=True, name="deliver_sms", max_retries=5, default_retry_delay=5)
|
||||||
|
@statsd(namespace="tasks")
|
||||||
|
def deliver_sms(self, notification_id):
|
||||||
|
try:
|
||||||
|
send_to_providers.send_sms_to_provider(notification_id)
|
||||||
|
except Exception as e:
|
||||||
|
try:
|
||||||
|
current_app.logger.error(
|
||||||
|
"RETRY: SMS notification {} failed".format(notification_id)
|
||||||
|
)
|
||||||
|
current_app.logger.exception(e)
|
||||||
|
self.retry(queue="retry", countdown=retry_iteration_to_delay(self.request.retries))
|
||||||
|
except self.MaxRetriesExceededError:
|
||||||
|
current_app.logger.error(
|
||||||
|
"RETRY FAILED: task send_sms_to_provider failed for notification {}".format(notification_id),
|
||||||
|
e
|
||||||
|
)
|
||||||
|
update_notification_status_by_id(notification_id, 'technical-failure')
|
||||||
|
|
||||||
|
|
||||||
|
@notify_celery.task(bind=True, name="deliver_email", max_retries=5, default_retry_delay=5)
|
||||||
|
@statsd(namespace="tasks")
|
||||||
|
def deliver_email(self, notification_id):
|
||||||
|
try:
|
||||||
|
send_to_providers.send_email_response(notification_id)
|
||||||
|
except Exception as e:
|
||||||
|
try:
|
||||||
|
current_app.logger.error(
|
||||||
|
"RETRY: Email notification {} failed".format(notification_id)
|
||||||
|
)
|
||||||
|
current_app.logger.exception(e)
|
||||||
|
self.retry(queue="retry", countdown=retry_iteration_to_delay(self.request.retries))
|
||||||
|
except self.MaxRetriesExceededError:
|
||||||
|
current_app.logger.error(
|
||||||
|
"RETRY FAILED: task send_email_to_provider failed for notification {}".format(notification_id),
|
||||||
|
e
|
||||||
|
)
|
||||||
|
update_notification_status_by_id(notification_id, 'technical-failure')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@notify_celery.task(bind=True, name="send-sms-to-provider", max_retries=5, default_retry_delay=5)
|
@notify_celery.task(bind=True, name="send-sms-to-provider", max_retries=5, default_retry_delay=5)
|
||||||
@statsd(namespace="tasks")
|
@statsd(namespace="tasks")
|
||||||
def send_sms_to_provider(self, service_id, notification_id):
|
def send_sms_to_provider(self, service_id, notification_id):
|
||||||
|
|||||||
34
app/delivery/rest.py
Normal file
34
app/delivery/rest.py
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
from flask import Blueprint, jsonify
|
||||||
|
|
||||||
|
from app.delivery import send_to_providers
|
||||||
|
from app.models import EMAIL_TYPE
|
||||||
|
from app.celery import provider_tasks
|
||||||
|
from sqlalchemy.orm.exc import NoResultFound
|
||||||
|
|
||||||
|
delivery = Blueprint('delivery', __name__)
|
||||||
|
|
||||||
|
from app.errors import (
|
||||||
|
register_errors,
|
||||||
|
InvalidRequest
|
||||||
|
)
|
||||||
|
|
||||||
|
register_errors(delivery)
|
||||||
|
|
||||||
|
|
||||||
|
@delivery.route('/deliver/notification/<uuid:notification_id>', methods=['POST'])
|
||||||
|
def send_notification_to_provider(notification_type, notification_id):
|
||||||
|
|
||||||
|
if notification_type == EMAIL_TYPE:
|
||||||
|
send_response(send_to_providers.send_email_response, provider_tasks.deliver_email, notification_id, 'send-email')
|
||||||
|
else:
|
||||||
|
send_response(send_to_providers.send_sms_response, provider_tasks.deliver_sms, notification_id, 'send-sms')
|
||||||
|
return jsonify({}), 204
|
||||||
|
|
||||||
|
|
||||||
|
def send_response(send_call, task_call, notification_id, queue):
|
||||||
|
try:
|
||||||
|
send_call(notification_id)
|
||||||
|
except NoResultFound as e:
|
||||||
|
raise InvalidRequest(e, status_code=404)
|
||||||
|
except Exception as e:
|
||||||
|
task_call.apply_async((str(notification_id)), queue=queue)
|
||||||
@@ -20,10 +20,9 @@ from app.dao.templates_dao import dao_get_template_by_id
|
|||||||
from app.models import SMS_TYPE, KEY_TYPE_TEST, BRANDING_ORG, EMAIL_TYPE
|
from app.models import SMS_TYPE, KEY_TYPE_TEST, BRANDING_ORG, EMAIL_TYPE
|
||||||
|
|
||||||
|
|
||||||
def send_sms_to_provider(notification_id):
|
def send_sms_to_provider(notification):
|
||||||
notification = get_notification_by_id(notification_id)
|
|
||||||
service = dao_fetch_service_by_id(notification.service_id)
|
service = dao_fetch_service_by_id(notification.service_id)
|
||||||
provider = provider_to_use(SMS_TYPE, notification_id)
|
provider = provider_to_use(SMS_TYPE, notification.id)
|
||||||
if notification.status == 'created':
|
if notification.status == 'created':
|
||||||
template_model = dao_get_template_by_id(notification.template_id, notification.template_version)
|
template_model = dao_get_template_by_id(notification.template_id, notification.template_version)
|
||||||
template = Template(
|
template = Template(
|
||||||
@@ -33,7 +32,7 @@ def send_sms_to_provider(notification_id):
|
|||||||
)
|
)
|
||||||
if service.research_mode or notification.key_type == KEY_TYPE_TEST:
|
if service.research_mode or notification.key_type == KEY_TYPE_TEST:
|
||||||
send_sms_response.apply_async(
|
send_sms_response.apply_async(
|
||||||
(provider.get_name(), str(notification_id), notification.to), queue='research-mode'
|
(provider.get_name(), str(notification.id), notification.to), queue='research-mode'
|
||||||
)
|
)
|
||||||
notification.billable_units = 0
|
notification.billable_units = 0
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -1,31 +1,8 @@
|
|||||||
import uuid
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
from celery.exceptions import MaxRetriesExceededError
|
from celery.exceptions import MaxRetriesExceededError
|
||||||
from unittest.mock import ANY, call
|
|
||||||
from notifications_utils.recipients import validate_phone_number, format_phone_number
|
|
||||||
|
|
||||||
import app
|
|
||||||
from app import statsd_client, mmg_client
|
|
||||||
from app.celery import provider_tasks
|
from app.celery import provider_tasks
|
||||||
from app.celery.provider_tasks import send_sms_to_provider, send_email_to_provider
|
from app.celery.provider_tasks import send_sms_to_provider, send_email_to_provider
|
||||||
from app.celery.research_mode_tasks import send_sms_response, send_email_response
|
|
||||||
from app.clients.email import EmailClientException
|
from app.clients.email import EmailClientException
|
||||||
from app.clients.sms import SmsClientException
|
from app.models import Notification
|
||||||
from app.dao import notifications_dao, provider_details_dao
|
|
||||||
from app.dao import provider_statistics_dao
|
|
||||||
from app.dao.provider_statistics_dao import get_provider_statistics
|
|
||||||
from app.models import (
|
|
||||||
Notification,
|
|
||||||
NotificationStatistics,
|
|
||||||
Job,
|
|
||||||
Organisation,
|
|
||||||
KEY_TYPE_NORMAL,
|
|
||||||
KEY_TYPE_TEST,
|
|
||||||
BRANDING_ORG,
|
|
||||||
BRANDING_BOTH
|
|
||||||
)
|
|
||||||
from tests.app.conftest import sample_notification
|
from tests.app.conftest import sample_notification
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import pytest
|
|||||||
from mock import ANY
|
from mock import ANY
|
||||||
|
|
||||||
import app
|
import app
|
||||||
|
from sqlalchemy.orm.exc import NoResultFound
|
||||||
from app import mmg_client
|
from app import mmg_client
|
||||||
from app.dao import (provider_details_dao, notifications_dao, provider_statistics_dao)
|
from app.dao import (provider_details_dao, notifications_dao, provider_statistics_dao)
|
||||||
from app.dao.provider_statistics_dao import get_provider_statistics
|
from app.dao.provider_statistics_dao import get_provider_statistics
|
||||||
@@ -46,6 +47,18 @@ def test_should_return_highest_priority_active_provider(notify_db, notify_db_ses
|
|||||||
assert send_to_providers.provider_to_use('sms', '1234').name == first.identifier
|
assert send_to_providers.provider_to_use('sms', '1234').name == first.identifier
|
||||||
|
|
||||||
|
|
||||||
|
def test_raises_not_found_exception_if_no_notification_for_id(notify_db, notify_db_session, mocker):
|
||||||
|
mocker.patch('app.mmg_client.send_sms')
|
||||||
|
mocker.patch('app.mmg_client.get_name', return_value="mmg")
|
||||||
|
notification_id = uuid.uuid4()
|
||||||
|
|
||||||
|
with pytest.raises(NoResultFound) as exc:
|
||||||
|
send_to_providers.send_sms_to_provider(notification_id)
|
||||||
|
|
||||||
|
assert str(exc.value) == "No notification for {}".format(str(notification_id))
|
||||||
|
app.mmg_client.send_sms.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
def test_should_send_personalised_template_to_correct_sms_provider_and_persist(
|
def test_should_send_personalised_template_to_correct_sms_provider_and_persist(
|
||||||
notify_db,
|
notify_db,
|
||||||
notify_db_session,
|
notify_db_session,
|
||||||
|
|||||||
Reference in New Issue
Block a user