Пример #1
0
def _check_and_queue_callback_task(notification):
    # queue callback task only if the service_callback_api exists
    service_callback_api = get_service_delivery_status_callback_api_for_service(service_id=notification.service_id)
    if service_callback_api:
        notification_data = create_delivery_status_callback_data(notification, service_callback_api)
        send_delivery_status_to_service.apply_async([str(notification.id), notification_data],
                                                    queue=QueueNames.CALLBACKS)
Пример #2
0
def test_ses_callback_should_update_notification_status(
        client, notify_db_session, sample_email_template, mocker):
    with freeze_time('2001-01-01T12:00:00'):
        mocker.patch('app.statsd_client.incr')
        mocker.patch('app.statsd_client.timing_with_dates')
        send_mock = mocker.patch(
            'app.celery.service_callback_tasks.send_delivery_status_to_service.apply_async'
        )
        notification = create_notification(
            template=sample_email_template,
            status='sending',
            reference='ref',
        )
        callback_api = create_service_callback_api(
            service=sample_email_template.service,
            url="https://original_url.com")
        assert get_notification_by_id(notification.id).status == 'sending'

        assert process_ses_results(ses_notification_callback(reference='ref'))
        assert get_notification_by_id(notification.id).status == 'delivered'
        statsd_client.timing_with_dates.assert_any_call(
            "callback.ses.elapsed-time", datetime.utcnow(),
            notification.sent_at)
        statsd_client.incr.assert_any_call("callback.ses.delivered")
        updated_notification = Notification.query.get(notification.id)
        encrypted_data = create_delivery_status_callback_data(
            updated_notification, callback_api)
        send_mock.assert_called_once_with(
            [str(notification.id), encrypted_data], queue="service-callbacks")
Пример #3
0
def test_outcome_statistics_called_for_successful_callback(
        sample_notification, mocker):
    mocker.patch(
        'app.notifications.process_client_response.notifications_dao.update_notification_status_by_id',
        return_value=sample_notification)
    send_mock = mocker.patch(
        'app.celery.service_callback_tasks.send_delivery_status_to_service.apply_async'
    )
    callback_api = create_service_callback_api(
        service=sample_notification.service,
        url="https://original_url.com",
        notification_statuses=NOTIFICATION_STATUS_TYPES)
    reference = str(uuid.uuid4())

    success, error = process_sms_client_response(status='3',
                                                 provider_reference=reference,
                                                 client_name='MMG')
    assert success == "MMG callback succeeded. reference {} updated".format(
        str(reference))
    assert error is None
    encrypted_data = create_delivery_status_callback_data(
        sample_notification, callback_api)
    send_mock.assert_called_once_with(
        [str(sample_notification.id), encrypted_data],
        queue="service-callbacks")
def process_service_callback(notification):
    if notification.status != NOTIFICATION_PENDING:
        service_callback_api = get_service_delivery_status_callback_api_for_service(service_id=notification.service_id)
        # queue callback task only if the service_callback_api exists
        if service_callback_api:
            encrypted_notification = create_delivery_status_callback_data(notification, service_callback_api)
            send_delivery_status_to_service.apply_async([notification.id, encrypted_notification],
                                                        queue=QueueNames.CALLBACKS)
Пример #5
0
def test_outcome_statistics_called_for_successful_callback(sample_notification, mocker):
    send_mock = mocker.patch(
        'app.celery.service_callback_tasks.send_delivery_status_to_service.apply_async'
    )
    callback_api = create_service_callback_api(service=sample_notification.service, url="https://original_url.com")
    reference = str(sample_notification.id)

    process_sms_client_response('3', reference, 'MMG')

    encrypted_data = create_delivery_status_callback_data(sample_notification, callback_api)
    send_mock.assert_called_once_with([reference, encrypted_data],
                                      queue="service-callbacks")
def test_timeout_notifications_sends_status_update_to_service(client, sample_template, mocker):
    callback_api = create_service_callback_api(service=sample_template.service)
    mocked = mocker.patch('app.celery.service_callback_tasks.send_delivery_status_to_service.apply_async')
    notification = create_notification(
        template=sample_template,
        status='sending',
        created_at=datetime.utcnow() - timedelta(
            seconds=current_app.config.get('SENDING_NOTIFICATIONS_TIMEOUT_PERIOD') + 10))
    timeout_notifications()

    encrypted_data = create_delivery_status_callback_data(notification, callback_api)
    mocked.assert_called_once_with([str(notification.id), encrypted_data], queue=QueueNames.CALLBACKS)
def _process_for_status(notification_status,
                        client_name,
                        provider_reference,
                        detailed_status_code=None):
    # record stats
    if client_name == 'Twilio':
        notification = notifications_dao.update_notification_status_by_reference(
            reference=provider_reference, status=notification_status)
    else:
        notification = notifications_dao.update_notification_status_by_id(
            notification_id=provider_reference,
            status=notification_status,
            sent_by=client_name.lower(),
            detailed_status_code=detailed_status_code)

    if not notification:
        return

    statsd_client.incr('callback.{}.{}'.format(client_name.lower(),
                                               notification_status))

    if notification.sent_at:
        statsd_client.timing_with_dates(
            'callback.{}.elapsed-time'.format(client_name.lower()),
            datetime.utcnow(), notification.sent_at)

    if notification.billable_units == 0:
        service = notification.service
        template_model = dao_get_template_by_id(notification.template_id,
                                                notification.template_version)

        template = SMSMessageTemplate(
            template_model.__dict__,
            values=notification.personalisation,
            prefix=service.name,
            show_prefix=service.prefix_sms,
        )
        notification.billable_units = template.fragment_count
        notifications_dao.dao_update_notification(notification)

    if notification_status != NOTIFICATION_PENDING:
        service_callback_api = get_service_delivery_status_callback_api_for_service(
            service_id=notification.service_id)
        # queue callback task only if the service_callback_api exists
        if service_callback_api:
            encrypted_notification = create_delivery_status_callback_data(
                notification, service_callback_api)
            send_delivery_status_to_service.apply_async(
                [str(notification.id), encrypted_notification],
                queue=QueueNames.CALLBACKS)
Пример #8
0
def check_for_callback_and_send_delivery_status_to_service(notification):
    service_callback_api = get_service_delivery_status_callback_api_for_service(
        service_id=notification.service_id)

    # If a status callback was provided on the notification or if the service
    # has a service_callback_api record, then queue the callback task.
    if (notification.status_callback_url and
            notification.status_callback_bearer_token) or service_callback_api:
        encrypted_notification = create_delivery_status_callback_data(
            notification, service_callback_api)

        send_delivery_status_to_service.apply_async(
            [str(notification.id), encrypted_notification],
            queue=QueueNames.CALLBACKS,
        )
Пример #9
0
def timeout_notifications():
    technical_failure_notifications, temporary_failure_notifications = \
        dao_timeout_notifications(current_app.config.get('SENDING_NOTIFICATIONS_TIMEOUT_PERIOD'))

    notifications = technical_failure_notifications + temporary_failure_notifications
    for notification in notifications:
        # queue callback task only if the service_callback_api exists
        service_callback_api = get_service_delivery_status_callback_api_for_service(service_id=notification.service_id)
        if service_callback_api:
            encrypted_notification = create_delivery_status_callback_data(notification, service_callback_api)
            send_delivery_status_to_service.apply_async([str(notification.id), encrypted_notification],
                                                        queue=QueueNames.CALLBACKS)

    current_app.logger.info(
        "Timeout period reached for {} notifications, status has been updated.".format(len(notifications)))
    if technical_failure_notifications:
        message = "{} notifications have been updated to technical-failure because they " \
                  "have timed out and are still in created.Notification ids: {}".format(
                      len(technical_failure_notifications), [str(x.id) for x in technical_failure_notifications])
        raise NotificationTechnicalFailureException(message)
Пример #10
0
def check_for_callback_and_send_delivery_status_to_service(notification):
    service_callback_api = get_service_delivery_status_callback_api_for_service(
        service_id=notification.service_id)

    # If a status callback was provided on the notification or if the service
    # has a service_callback_api record, then queue the callback task.
    if (notification.status_callback_url and
            notification.status_callback_bearer_token) or service_callback_api:
        if dao_service_callbacks_are_failing(notification.service_id):
            current_app.logger.warning(
                f"send_delivery_status_to_service not called for notification_id: {notification.id} due to failing service_id: {notification.service_id}"
            )
            return

        encrypted_notification = create_delivery_status_callback_data(
            notification, service_callback_api)
        send_delivery_status_to_service.apply_async(
            [str(notification.id), encrypted_notification],
            queue=QueueNames.CALLBACKS,
        )
Пример #11
0
def test_delivery_status_callback_calls_for_notification_with_callback(
        sample_notification_with_callback, mocker):
    mocker.patch(
        'app.notifications.process_client_response.notifications_dao.update_notification_status_by_id',
        return_value=sample_notification_with_callback)
    send_mock = mocker.patch(
        'app.celery.service_callback_tasks.send_delivery_status_to_service.apply_async'
    )
    reference = str(uuid.uuid4())

    success, error = process_sms_client_response(status='delivered',
                                                 provider_reference=reference,
                                                 client_name='twilio')
    assert success == "twilio callback succeeded. reference {} updated".format(
        str(reference))
    assert error is None
    encrypted_data = create_delivery_status_callback_data(
        sample_notification_with_callback, None)
    send_mock.assert_called_once_with(
        [str(sample_notification_with_callback.id), encrypted_data],
        queue="service-callbacks",
    )
Пример #12
0
def test_ses_callback_should_call_send_delivery_status_to_service(
        client, sample_email_template, mocker):
    send_mock = mocker.patch(
        'app.celery.service_callback_tasks.send_delivery_status_to_service.apply_async'
    )
    notification = create_notification(
        template=sample_email_template,
        status='sending',
        reference='ref',
    )

    callback_api = create_service_callback_api(
        service=sample_email_template.service, url="https://original_url.com")
    mocked_callback_api = mocker.Mock(url=callback_api.url,
                                      bearer_token=callback_api.bearer_token)
    process_ses_receipts_tasks.process_ses_results(
        ses_notification_callback(reference='ref'))

    updated_notification = Notification.query.get(notification.id)

    encrypted_data = create_delivery_status_callback_data(
        updated_notification, mocked_callback_api)
    send_mock.assert_called_once_with([str(notification.id), encrypted_data],
                                      queue="service-callbacks")
Пример #13
0
def replay_service_callbacks(file_name, service_id):
    print("Start send service callbacks for service: ", service_id)
    callback_api = get_service_delivery_status_callback_api_for_service(
        service_id=service_id)
    if not callback_api:
        print("Callback api was not found for service: {}".format(service_id))
        return

    errors = []
    notifications = []
    file = open(file_name)

    for ref in file:
        try:
            notification = Notification.query.filter_by(
                client_reference=ref.strip()).one()
            notifications.append(notification)
        except NoResultFound:
            errors.append(
                "Reference: {} was not found in notifications.".format(ref))

    for e in errors:
        print(e)
    if errors:
        raise Exception(
            "Some notifications for the given references were not found")

    for n in notifications:
        encrypted_status_update = create_delivery_status_callback_data(
            n, callback_api)
        send_delivery_status_to_service.apply_async(
            [str(n.id), encrypted_status_update], queue=QueueNames.CALLBACKS)

    print(
        "Replay service status for service: {}. Sent {} notification status updates to the queue"
        .format(service_id, len(notifications)))
def _process_for_status(notification_status, client_name, provider_reference):
    # record stats
    notification = notifications_dao.update_notification_status_by_id(
        provider_reference, notification_status)
    if not notification:
        current_app.logger.warning(
            "{} callback failed: notification {} either not found or already updated "
            "from sending. Status {}".format(client_name, provider_reference,
                                             notification_status))
        return

    statsd_client.incr('callback.{}.{}'.format(client_name.lower(),
                                               notification_status))

    if not notification.sent_by:
        set_notification_sent_by(notification, client_name.lower())

    if notification.sent_at:
        statsd_client.timing_with_dates(
            'callback.{}.elapsed-time'.format(client_name.lower()),
            datetime.utcnow(), notification.sent_at)

    # queue callback task only if the service_callback_api exists
    service_callback_api = get_service_delivery_status_callback_api_for_service(
        service_id=notification.service_id)

    if service_callback_api:
        encrypted_notification = create_delivery_status_callback_data(
            notification, service_callback_api)
        send_delivery_status_to_service.apply_async(
            [str(notification.id), encrypted_notification],
            queue=QueueNames.CALLBACKS)

    success = "{} callback succeeded. reference {} updated".format(
        client_name, provider_reference)
    return success
Пример #15
0
def _set_up_data_for_status_update(callback_api, notification):
    return create_delivery_status_callback_data(notification, callback_api)