<commit_before>from datetime import datetime

from flask import current_app

from app import cbc_proxy_client, notify_celery, zendesk_client
from app.clients.cbc_proxy import CBCProxyRetryableException
from app.config import QueueNames
from app.dao.broadcast_message_dao import (
    create_broadcast_provider_message,
    dao_get_broadcast_event_by_id,
    update_broadcast_provider_message_status,
)
from app.models import (
    BroadcastEventMessageType,
    BroadcastProvider,
    BroadcastProviderMessageStatus,
)
from app.utils import format_sequential_number


class BroadcastIntegrityError(Exception):
    pass


def get_retry_delay(retry_count):
    """
    Given a count of retries so far, return a delay for the next one.
    `retry_count` should be 0 the first time a task fails.
    """
    # TODO: replace with celery's built in exponential backoff

    # 2 to the power of x. 1, 2, 4, 8, 16, 32, ...
    delay = 2**retry_count
    # never wait longer than 4 minutes
    return min(delay, 240)


def check_event_is_authorised_to_be_sent(broadcast_event, provider):
    if not broadcast_event.service.active:
        raise BroadcastIntegrityError(
            f'Cannot send broadcast_event {broadcast_event.id} ' +
            f'to provider {provider}: the service is suspended'
        )

    if broadcast_event.service.restricted:
        raise BroadcastIntegrityError(
            f'Cannot send broadcast_event {broadcast_event.id} ' +
            f'to provider {provider}: the service is not live'
        )

    if broadcast_event.broadcast_message.stubbed:
        raise BroadcastIntegrityError(
            f'Cannot send broadcast_event {broadcast_event.id} ' +
            f'to provider {provider}: the broadcast message is stubbed'
        )


def check_event_makes_sense_in_sequence(broadcast_event, provider):
    """
    If any previous event hasn't sent yet for that provider, then we shouldn't send the current event. Instead, fail and
    raise a zendesk ticket - so that a notify team member can assess the state of the previous messages, and if necessary, can
    replay the `send_broadcast_provider_message` task if the previous message has now been sent.

    Note: This is called before the new broadcast_provider_message is created.

    # Help, I've come across this code following a pagerduty alert, what should I do?

    1. Find the failing broadcast_provider_message associated with the previous event that caused this to trip.
    2. If that provider message is still failing to send, fix the issue causing that. The task to send that previous
       message might still be retrying in the background - look for logs related to that task.
    3. If that provider message has sent succesfully, you might need to send this task off depending on context. This
       might not always be true though, for example, it may not be necessary to send a cancel if the original alert has
       already expired.
    4. If you need to re-send this task off again, you'll need to run the following command on paas:
       `send_broadcast_provider_message.apply_async(args=(broadcast_event_id, provider), queue=QueueNames.BROADCASTS)`
    """
    current_provider_message = broadcast_event.get_provider_message(provider)
    # if this is the first time a task is being executed, it won't have a provider message yet
    if current_provider_message and current_provider_message.status != BroadcastProviderMessageStatus.SENDING:
        raise BroadcastIntegrityError(
            f'Cannot send broadcast_event {broadcast_event.id} ' +
            f'to provider {provider}: ' +
            f'It is in status {current_provider_message.status}'
        )

    if broadcast_event.transmitted_finishes_at < datetime.utcnow():
        raise BroadcastIntegrityError(
            f'Cannot send broadcast_event {broadcast_event.id} ' +<commit_msg>Fix flake8<commit_after>from datetime import datetime

from flask import current_app

from app import cbc_proxy_client, notify_celery, zendesk_client
from app.clients.cbc_proxy import CBCProxyRetryableException
from app.config import QueueNames
from app.dao.broadcast_message_dao import (
    create_broadcast_provider_message,
    dao_get_broadcast_event_by_id,
    update_broadcast_provider_message_status,
)
from app.models import (
    BroadcastEventMessageType,
    BroadcastProvider,
    BroadcastProviderMessageStatus,
)
from app.utils import format_sequential_number


class BroadcastIntegrityError(Exception):
    pass


def get_retry_delay(retry_count):
    """
    Given a count of retries so far, return a delay for the next one.
    `retry_count` should be 0 the first time a task fails.
    """
    # TODO: replace with celery's built in exponential backoff

    # 2 to the power of x. 1, 2, 4, 8, 16, 32, ...
    delay = 2**retry_count
    # never wait longer than 4 minutes
    return min(delay, 240)


def check_event_is_authorised_to_be_sent(broadcast_event, provider):
    if not broadcast_event.service.active:
        raise BroadcastIntegrityError(
            f'Cannot send broadcast_event {broadcast_event.id} ' +
            f'to provider {provider}: the service is suspended'
        )

    if broadcast_event.service.restricted:
        raise BroadcastIntegrityError(
            f'Cannot send broadcast_event {broadcast_event.id} ' +
            f'to provider {provider}: the service is not live'
        )

    if broadcast_event.broadcast_message.stubbed:
        raise BroadcastIntegrityError(
            f'Cannot send broadcast_event {broadcast_event.id} ' +
            f'to provider {provider}: the broadcast message is stubbed'
        )


def check_event_makes_sense_in_sequence(broadcast_event, provider):
    """
    If any previous event hasn't sent yet for that provider, then we shouldn't send the current event. Instead, fail and
    raise a zendesk ticket - so that a notify team member can assess the state of the previous messages, and if
    necessary, can replay the `send_broadcast_provider_message` task if the previous message has now been sent.

    Note: This is called before the new broadcast_provider_message is created.

    # Help, I've come across this code following a pagerduty alert, what should I do?

    1. Find the failing broadcast_provider_message associated with the previous event that caused this to trip.
    2. If that provider message is still failing to send, fix the issue causing that. The task to send that previous
       message might still be retrying in the background - look for logs related to that task.
    3. If that provider message has sent succesfully, you might need to send this task off depending on context. This
       might not always be true though, for example, it may not be necessary to send a cancel if the original alert has
       already expired.
    4. If you need to re-send this task off again, you'll need to run the following command on paas:
       `send_broadcast_provider_message.apply_async(args=(broadcast_event_id, provider), queue=QueueNames.BROADCASTS)`
    """
    current_provider_message = broadcast_event.get_provider_message(provider)
    # if this is the first time a task is being executed, it won't have a provider message yet
    if current_provider_message and current_provider_message.status != BroadcastProviderMessageStatus.SENDING:
        raise BroadcastIntegrityError(
            f'Cannot send broadcast_event {broadcast_event.id} ' +
            f'to provider {provider}: ' +
            f'It is in status {current_provider_message.status}'
        )

    if broadcast_event.transmitted_finishes_at < datetime.utcnow():
        raise BroadcastIntegrityError(
            f'Cannot send broadcast_event {broadcast_event.id} ' +
{'fraction_non_alphanumeric': 0.05543323403704183, 'fraction_numerical': 0.005051159176272504, 'mean_word_length': 3.537015276145711, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2348688', 'n_tokens_mistral': 2134, 'n_tokens_neox': 2064, 'n_words': 791}