Skip to content

Commit

Permalink
#2205 - Comp and Pen Batches (#2206)
Browse files Browse the repository at this point in the history
  • Loading branch information
k-macmillan authored Dec 27, 2024
1 parent 402e961 commit 0b61019
Show file tree
Hide file tree
Showing 15 changed files with 203 additions and 740 deletions.
119 changes: 119 additions & 0 deletions app/celery/process_comp_and_pen.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
from dataclasses import dataclass
from uuid import uuid4

from flask import current_app
from sqlalchemy.orm.exc import NoResultFound

from notifications_utils.statsd_decorators import statsd

from app import notify_celery
from app.dao.service_sms_sender_dao import dao_get_service_sms_sender_by_id
from app.models import (
Service,
Template,
)
from app.notifications.send_notifications import lookup_notification_sms_setup_data, send_notification_bypass_route
from app.va.identifier import IdentifierType


@dataclass
class DynamoRecord:
participant_id: str
payment_amount: str
vaprofile_id: str


@notify_celery.task(name='comp-and-pen-batch-process')
@statsd(namespace='tasks')
def comp_and_pen_batch_process(records: list[dict[str, str]]) -> None:
"""Process batches of Comp and Pen notification requests.
Args:
records (list[dict[str, str]]): The incoming records
"""
current_app.logger.debug(f'comp_and_pen_batch_process records: {records}')

# Grab all the necessary data
try:
service, template, sms_sender_id = lookup_notification_sms_setup_data(
current_app.config['COMP_AND_PEN_SERVICE_ID'],
current_app.config['COMP_AND_PEN_TEMPLATE_ID'],
current_app.config['COMP_AND_PEN_SMS_SENDER_ID'],
)
reply_to_text = dao_get_service_sms_sender_by_id(service.id, sms_sender_id).sms_sender
except (AttributeError, NoResultFound, ValueError):
current_app.logger.exception('Unable to send comp and pen notifications due to improper configuration')
raise

_send_comp_and_pen_sms(
service,
template,
sms_sender_id,
reply_to_text,
[DynamoRecord(**item) for item in records],
current_app.config['COMP_AND_PEN_PERF_TO_NUMBER'],
)


def _send_comp_and_pen_sms(
service: Service,
template: Template,
sms_sender_id: str,
reply_to_text: str,
comp_and_pen_messages: list[DynamoRecord],
perf_to_number: str,
) -> None:
"""
Sends scheduled SMS notifications to recipients based on the provided parameters.
Args:
:param service (Service): The service used to send the SMS notifications.
:param template (Template): The template used for the SMS notifications.
:param sms_sender_id (str): The ID of the SMS sender.
:param reply_to_text (str): The text a Veteran can reply to.
:param comp_and_pen_messages (list[DynamoRecord]): A list of DynamoRecord from the dynamodb table containing
the details needed to send the messages.
:param perf_to_number (str): The recipient's phone number.
Raises:
Exception: If there is an error while sending the SMS notification.
"""

for item in comp_and_pen_messages:
current_app.logger.debug('sending - record from dynamodb: %s', item.participant_id)

# Use perf_to_number as the recipient if available. Otherwise, use vaprofile_id as recipient_item.
recipient_item = (
None
if perf_to_number is not None
else {
'id_type': IdentifierType.VA_PROFILE_ID.value,
'id_value': item.vaprofile_id,
}
)

try:
# call generic method to send messages
send_notification_bypass_route(
service=service,
template=template,
reply_to_text=reply_to_text,
personalisation={'amount': item.payment_amount},
sms_sender_id=sms_sender_id,
recipient=perf_to_number,
recipient_item=recipient_item,
notification_id=uuid4(),
)
except Exception:
current_app.logger.exception(
'Error attempting to send Comp and Pen notification with '
'send_comp_and_pen_sms | record from dynamodb: %s',
item.participant_id,
)
else:
if perf_to_number is not None:
current_app.logger.info(
'Notification sent using Perf simulated number %s instead of vaprofile_id', perf_to_number
)

current_app.logger.info('Notification sent to queue for record from dynamodb: %s', item.participant_id)
69 changes: 0 additions & 69 deletions app/celery/scheduled_tasks.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
from datetime import datetime, timedelta
from time import monotonic

from botocore.exceptions import ClientError
from flask import current_app
from notifications_utils.statsd_decorators import statsd
from sqlalchemy import and_, select
Expand All @@ -28,11 +26,8 @@
dao_old_letters_with_created_status,
)
from app.dao.users_dao import delete_codes_older_created_more_than_a_day_ago
from app.feature_flags import is_feature_enabled, FeatureFlag
from app.integrations.comp_and_pen.scheduled_message_helpers import CompPenMsgHelper
from app.models import Job
from app.notifications.process_notifications import send_notification_to_queue
from app.notifications.send_notifications import lookup_notification_sms_setup_data
from app.v2.errors import JobIncompleteError


Expand Down Expand Up @@ -196,67 +191,3 @@ def check_templated_letter_state():
message=msg,
ticket_type=zendesk_client.TYPE_INCIDENT,
)


@notify_celery.task(name='send-scheduled-comp-and-pen-sms')
@statsd(namespace='tasks')
def send_scheduled_comp_and_pen_sms() -> None:
start_time = monotonic()
# this is the agreed upon message per 1 minute limit
messages_per_min = 90

# get config info
dynamodb_table_name = current_app.config['COMP_AND_PEN_DYNAMODB_TABLE_NAME']
service_id = current_app.config['COMP_AND_PEN_SERVICE_ID']
template_id = current_app.config['COMP_AND_PEN_TEMPLATE_ID']
sms_sender_id = current_app.config['COMP_AND_PEN_SMS_SENDER_ID']
# Perf uses the AWS simulated delivered number
perf_to_number = current_app.config['COMP_AND_PEN_PERF_TO_NUMBER']

comp_pen_helper = CompPenMsgHelper(dynamodb_table_name=dynamodb_table_name)

current_app.logger.debug('send_scheduled_comp_and_pen_sms connecting to dynamodb...')
try:
comp_pen_helper._connect_to_dynamodb()
except ClientError as e:
current_app.logger.critical(
'Unable to connect to dynamodb table with name %s - exception: %s', dynamodb_table_name, e
)
raise

current_app.logger.debug('... connected to dynamodb in send_scheduled_comp_and_pen_sms')
current_app.logger.info('dynamo connection took: %s seconds', monotonic() - start_time)

# get messages to send
try:
comp_and_pen_messages: list = comp_pen_helper.get_dynamodb_comp_pen_messages(messages_per_min)
except Exception as e:
current_app.logger.critical(
'Exception trying to scan dynamodb table for send_scheduled_comp_and_pen_sms exception_type: %s - '
'exception_message: %s',
type(e),
e,
)
raise

current_app.logger.debug('send_scheduled_comp_and_pen_sms list of items from dynamodb: %s', comp_and_pen_messages)

# only continue if there are messages to update and send
if comp_and_pen_messages:
comp_pen_helper.remove_dynamo_item_is_processed(comp_and_pen_messages)

if is_feature_enabled(FeatureFlag.COMP_AND_PEN_MESSAGES_ENABLED):
# get the data necessary to send the notifications
service, template, sms_sender_id = lookup_notification_sms_setup_data(
service_id, template_id, sms_sender_id
)

comp_pen_helper.send_comp_and_pen_sms(
service=service,
template=template,
sms_sender_id=sms_sender_id,
comp_and_pen_messages=comp_and_pen_messages,
perf_to_number=perf_to_number,
)
else:
current_app.logger.info('Comp and Pen Notifications not sent to queue (feature flag disabled)')
7 changes: 1 addition & 6 deletions app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ class Config(object):
'task_serializer': 'json',
'imports': (
'app.celery.tasks',
'app.celery.process_comp_and_pen',
'app.celery.scheduled_tasks',
'app.celery.reporting_tasks',
'app.celery.nightly_tasks',
Expand Down Expand Up @@ -316,12 +317,6 @@ class Config(object):
'schedule': crontab(hour=4, minute=0),
'options': {'queue': QueueNames.PERIODIC},
},
'send-scheduled-comp-and-pen-sms': {
'task': 'send-scheduled-comp-and-pen-sms',
# Every 1 minute past every hour from 13 through 21 on every day-of-month from 22 through end-of-month
'schedule': crontab(hour='13-21', day_of_month='23-31', minute='*/1'),
'options': {'queue': QueueNames.PERIODIC},
},
'update-twilio-status': {
'task': 'update-twilio-status',
'schedule': crontab(hour='*', minute='*/5'),
Expand Down
1 change: 0 additions & 1 deletion app/feature_flags.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ class FeatureFlag(Enum):
PLATFORM_STATS_ENABLED = 'PLATFORM_STATS_ENABLED'
VA_SSO_ENABLED = 'VA_SSO_ENABLED'
V3_ENABLED = 'V3_ENABLED'
COMP_AND_PEN_MESSAGES_ENABLED = 'COMP_AND_PEN_MESSAGES_ENABLED'
VA_PROFILE_SMS_STATUS_ENABLED = 'VA_PROFILE_SMS_STATUS_ENABLED'


Expand Down
Loading

0 comments on commit 0b61019

Please sign in to comment.