Skip to content

Commit

Permalink
feat: batch reminder email sends to the Braze API campaign messages e…
Browse files Browse the repository at this point in the history
…ndpoint.
  • Loading branch information
iloveagent57 committed Mar 14, 2024
1 parent 24290a1 commit 404ab86
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 37 deletions.
54 changes: 28 additions & 26 deletions license_manager/apps/api/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,14 +211,14 @@ def send_reminder_email_task(custom_template_text, email_recipient_list, subscri
enterprise_contact_email = enterprise_customer.get('contact_email')

pending_license_by_email = {}
# We need to send these emails individually, because each email's text must be
# generated for every single user/activation_key
emails_for_aliasing = []
recipients = []
for pending_license in pending_licenses:
user_email = pending_license.user_email
emails_for_aliasing.append(user_email)
pending_license_by_email[user_email] = pending_license
license_activation_key = str(pending_license.activation_key)
braze_campaign_id = settings.BRAZE_REMIND_EMAIL_CAMPAIGN
braze_trigger_properties = {
trigger_properties = {
'TEMPLATE_GREETING': custom_template_text['greeting'],
'TEMPLATE_CLOSING': custom_template_text['closing'],
'license_activation_key': license_activation_key,
Expand All @@ -229,29 +229,31 @@ def send_reminder_email_task(custom_template_text, email_recipient_list, subscri
}
recipient = _aliased_recipient_object_from_email(user_email)
recipient['attributes'].update(get_license_tracking_properties(pending_license))
recipient['trigger_properties'] = trigger_properties
recipients.append(recipient)

try:
braze_client_instance = BrazeApiClient()
braze_client_instance.create_braze_alias(
[user_email],
ENTERPRISE_BRAZE_ALIAS_LABEL,
)
braze_client_instance.send_campaign_message(
braze_campaign_id,
recipients=[recipient],
trigger_properties=braze_trigger_properties,
)
logger.info(
f'{LICENSE_DEBUG_PREFIX} Sent license reminder email '
f'braze campaign {braze_campaign_id} to {recipient}'
)
except BrazeClientError as exc:
message = (
'Error hitting Braze API. '
f'reminder email to {user_email} for license failed.'
)
logger.exception(message)
raise exc
# Batch at the Braze API layer
try:
braze_client_instance = BrazeApiClient()
braze_client_instance.create_braze_alias(
emails_for_aliasing,
ENTERPRISE_BRAZE_ALIAS_LABEL,
)
braze_client_instance.send_campaign_message(
settings.BRAZE_REMIND_EMAIL_CAMPAIGN,
recipients=recipients,
)
logger.info(
f'{LICENSE_DEBUG_PREFIX} Sent license reminder emails '
f'braze campaign {settings.BRAZE_REMIND_EMAIL_CAMPAIGN} to {email_recipient_list}'
)
except BrazeClientError as exc:
message = (
'Error hitting Braze API. '
f'reminder email to {settings.BRAZE_REMIND_EMAIL_CAMPAIGN} for license failed.'
)
logger.exception(message)
raise exc

License.set_date_fields_to_now(pending_licenses, ['last_remind_date'])

Expand Down
27 changes: 18 additions & 9 deletions license_manager/apps/api/tests/test_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,8 @@ def test_send_reminder_email_task(self, mock_enterprise_client, mock_braze_clien
]
self.assertNotIn('[email protected]', called_emails)

expected_recipients = []
expected_alias_emails = []
for user_email in self.email_recipient_list:
expected_license = self.subscription_plan.licenses.get(
user_email=user_email
Expand All @@ -212,10 +214,7 @@ def test_send_reminder_email_task(self, mock_enterprise_client, mock_braze_clien
mock_enterprise_client().get_enterprise_customer_data.assert_any_call(
self.subscription_plan.enterprise_customer_uuid
)
mock_braze_client().create_braze_alias.assert_any_call(
[user_email],
ENTERPRISE_BRAZE_ALIAS_LABEL,
)
expected_alias_emails.append(user_email)

expected_trigger_properties = {
'TEMPLATE_GREETING': 'Hello',
Expand All @@ -234,11 +233,21 @@ def test_send_reminder_email_task(self, mock_enterprise_client, mock_braze_clien
},
}
expected_recipient['attributes'].update(get_license_tracking_properties(expected_license))
mock_braze_client().send_campaign_message.assert_any_call(
settings.BRAZE_ASSIGNMENT_EMAIL_CAMPAIGN,
recipients=[expected_recipient],
trigger_properties=expected_trigger_properties,
)
expected_recipient['trigger_properties'] = expected_trigger_properties
expected_recipients.append(expected_recipient)

# assert all emails sent for aliasing in a single call
actual_alias_call_emails = mock_braze_client.return_value.create_braze_alias.call_args_list[0][0][0]
assert sorted(expected_alias_emails) == sorted(actual_alias_call_emails)

# assert all recipients sent a campaign message in a single call
mock_send_message = mock_braze_client.return_value.send_campaign_message
actual_recipients_list = mock_send_message.call_args_list[0][1]['recipients']

def sort_key(x):
return x['attributes']['email']

assert sorted(expected_recipients, key=sort_key) == sorted(actual_recipients_list, key=sort_key)

# Verify the 'last_remind_date' of all licenses have been updated
assert_date_fields_correct(
Expand Down
2 changes: 1 addition & 1 deletion license_manager/apps/api/v1/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1986,7 +1986,7 @@ def test_remind_all(self, mock_send_reminder_emails_task):
pending_licenses = LicenseFactory.create_batch(3, status=constants.ASSIGNED)
self.subscription_plan.licenses.set(unassigned_licenses + pending_licenses)

with mock.patch('license_manager.apps.subscriptions.constants.LICENSE_BULK_OPERATION_BATCH_SIZE', new=2):
with mock.patch('license_manager.apps.subscriptions.constants.REMINDER_EMAIL_BATCH_SIZE', new=2):
response = self.api_client.post(self.remind_all_url, {'greeting': self.greeting, 'closing': self.closing})

assert response.status_code == status.HTTP_204_NO_CONTENT
Expand Down
2 changes: 1 addition & 1 deletion license_manager/apps/api/v1/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1006,7 +1006,7 @@ def remind_all(self, request, subscription_uuid=None):
return Response('Could not find any licenses pending activation', status=status.HTTP_404_NOT_FOUND)

# Send reminder emails in batches.
chunked_lists = chunks(assigned_license_emails, constants.LICENSE_BULK_OPERATION_BATCH_SIZE)
chunked_lists = chunks(assigned_license_emails, constants.REMINDER_EMAIL_BATCH_SIZE)
for assigned_license_email_chunk in chunked_lists:
send_reminder_email_task.delay(
utils.get_custom_text(request.data),
Expand Down
1 change: 1 addition & 0 deletions license_manager/apps/subscriptions/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ class SegmentEvents:
PENDING_ACCOUNT_CREATION_BATCH_SIZE = 100
LICENSE_SOURCE_BULK_OPERATION_BATCH_SIZE = 100
TRACK_LICENSE_CHANGES_BATCH_SIZE = 25
REMINDER_EMAIL_BATCH_SIZE = 50

# Num distinct catalog query validation batch size
VALIDATE_NUM_CATALOG_QUERIES_BATCH_SIZE = 100
Expand Down

0 comments on commit 404ab86

Please sign in to comment.