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)
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)
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)
def test_get_service_delivery_status_callback_api_for_service(sample_service):
    service_callback_api = create_service_callback_api(service=sample_service)
    result = get_service_delivery_status_callback_api_for_service(sample_service.id)
    assert result.id == service_callback_api.id
    assert result.url == service_callback_api.url
    assert result.bearer_token == service_callback_api.bearer_token
    assert result.created_at == service_callback_api.created_at
    assert result.updated_at == service_callback_api.updated_at
    assert result.updated_by_id == service_callback_api.updated_by_id
Beispiel #5
0
def test_no_service_delivery_status_callback_api_by_status(
        sample_service, saved_notification_statuses, query_notification_statuses
):
    create_service_callback_api(
        service=sample_service, notification_statuses=saved_notification_statuses
    )
    for notification_status in query_notification_statuses:
        result = get_service_delivery_status_callback_api_for_service(
            sample_service.id,
            notification_status=notification_status
        )
        assert result is None
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)
Beispiel #7
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,
        )
Beispiel #8
0
def test_existing_service_delivery_status_callback_api_by_status(sample_service, notification_statuses):
    service_callback_api = create_service_callback_api(
        service=sample_service, notification_statuses=notification_statuses
    )

    for notification_status in notification_statuses:
        result = get_service_delivery_status_callback_api_for_service(
            sample_service.id,
            notification_status=notification_status
        )
        assert result.id == service_callback_api.id
        assert result.url == service_callback_api.url
        assert result.bearer_token == service_callback_api.bearer_token
        assert result.created_at == service_callback_api.created_at
        assert result.updated_at == service_callback_api.updated_at
        assert result.updated_by_id == service_callback_api.updated_by_id
Beispiel #9
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:
        data = {
            "notification_id": str(n.id),
            "notification_client_reference": n.client_reference,
            "notification_to": n.to,
            "notification_status": n.status,
            "notification_created_at": n.created_at.strftime(DATETIME_FORMAT),
            "notification_updated_at": n.updated_at.strftime(DATETIME_FORMAT),
            "notification_sent_at": n.sent_at.strftime(DATETIME_FORMAT),
            "notification_type": n.notification_type,
            "service_callback_api_url": callback_api.url,
            "service_callback_api_bearer_token": callback_api.bearer_token,
        }
        encrypted_status_update = encryption.encrypt(data)
        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)))
Beispiel #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,
        )
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_encrypted_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
Beispiel #12
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_shortnumber_keyword_client_response(service, short_number, from_number, body, received_at,
                                                provider_ref, client_name):
    success = None
    errors = None

    parsed_datetime = iso8601.parse_date(received_at).replace(tzinfo=None)
    parsed_datetime = convert_local_timezone_to_utc(parsed_datetime)

    inbound = create_inbound_sms_keyword_object(service=service,
                                                content=body,
                                                from_number=from_number,
                                                provider_ref=provider_ref,
                                                date_received=parsed_datetime,
                                                provider_name=client_name)

    service_callback_api = get_service_delivery_status_callback_api_for_service(service_id=service.id)
    # queue callback task only if the service_callback_api exists
    if service_callback_api:
        encrypted_data = create_shortnumber_keyword_status_callback_data(inbound, service_callback_api)
        send_keyword_status_to_service.apply_async([encrypted_data],
                                                   queue=QueueNames.CALLBACKS)

    success = "{} callback succeeded. keyword stored".format(client_name)
    return success, errors