Skip to content

Commit

Permalink
Merge pull request #1923 from openedx/asaeed/ENT-7716
Browse files Browse the repository at this point in the history
[ENT-7716] feat: Truncate API Response before writing to DB
  • Loading branch information
justEhmadSaeed committed Oct 24, 2023
2 parents 2714365 + 9f243e0 commit d405e06
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 1 deletion.
3 changes: 3 additions & 0 deletions enterprise/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,3 +219,6 @@ class FulfillmentTypes:


SSO_BRAZE_CAMPAIGN_ID = 'a5f10d46-8093-4ce1-bab7-6df018d03660'

# The maximum length of a text field in the database.
MAX_ALLOWED_TEXT_LENGTH = 16_000_000
17 changes: 17 additions & 0 deletions enterprise/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
DEFAULT_CATALOG_CONTENT_FILTER,
LMS_API_DATETIME_FORMAT,
LMS_API_DATETIME_FORMAT_WITHOUT_TIMEZONE,
MAX_ALLOWED_TEXT_LENGTH,
PATHWAY_CUSTOMER_ADMIN_ENROLLMENT,
PROGRAM_TYPE_DESCRIPTION,
CourseModes,
Expand Down Expand Up @@ -2365,3 +2366,19 @@ def camelCase(string):
"""
output = ''.join(x for x in string.title() if x.isalnum())
return output[0].lower() + output[1:]


def truncate_string(string, max_length=MAX_ALLOWED_TEXT_LENGTH):
"""
Truncate a string to the specified max length.
If max length is not specified, it will be set to MAX_ALLOWED_TEXT_LENGTH.
Returns:
(tuple): (truncated_string, was_truncated)
"""
was_truncated = False
if len(string) > max_length:
truncated_string = string[:max_length]
was_truncated = True
return (truncated_string, was_truncated)
return (string, was_truncated)
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from django.apps import apps
from django.conf import settings

from enterprise.utils import localized_utcnow
from enterprise.utils import localized_utcnow, truncate_string
from integrated_channels.exceptions import ClientError
from integrated_channels.integrated_channel.client import IntegratedChannelApiClient
from integrated_channels.integrated_channel.transmitters import Transmitter
Expand Down Expand Up @@ -230,6 +230,13 @@ def _transmit_action(self, content_metadata_item_map, client_method, action_name
api_content_response = response_body
if was_successful:
api_content_response = self._filter_api_response(api_content_response, content_id)
(api_content_response, was_truncated) = truncate_string(api_content_response)
if was_truncated:
self._log_info(
f'integrated_channel_content_transmission_id={transmission.id}, '
f'api response truncated',
course_or_course_run_key=content_id
)
if transmission.api_record:
transmission.api_record.body = api_content_response
transmission.api_record.status_code = response_status_code
Expand Down
20 changes: 20 additions & 0 deletions tests/test_enterprise/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from django.conf import settings
from django.forms.models import model_to_dict

from enterprise.constants import MAX_ALLOWED_TEXT_LENGTH
from enterprise.models import EnterpriseCourseEnrollment, LicensedEnterpriseCourseEnrollment
from enterprise.utils import (
enroll_subsidy_users_in_courses,
Expand All @@ -22,6 +23,7 @@
localized_utcnow,
parse_lms_api_datetime,
serialize_notification_content,
truncate_string,
)
from test_utils import FAKE_UUIDS, TEST_PASSWORD, TEST_USERNAME, factories

Expand Down Expand Up @@ -516,3 +518,21 @@ def test_get_default_invite_key_expiration_date(self):
expiration_date = get_default_invite_key_expiration_date()
expected_expiration_date = current_time + timedelta(days=365)
self.assertEqual(expiration_date.date(), expected_expiration_date.date())

def test_truncate_string(self):
"""
Test that `truncate_string` returns the expected string.
"""
test_string_1 = 'This is a test string'
(truncated_string_1, was_truncated_1) = truncate_string(test_string_1, 10)
self.assertTrue(was_truncated_1)
self.assertEqual('This is a ', truncated_string_1)

(truncated_string_2, was_truncated_2) = truncate_string(test_string_1, 100)
self.assertFalse(was_truncated_2)
self.assertEqual('This is a test string', truncated_string_2)

test_string_2 = ''.rjust(MAX_ALLOWED_TEXT_LENGTH + 10, 'x')
(truncated_string, was_truncated) = truncate_string(test_string_2)
self.assertTrue(was_truncated)
self.assertEqual(len(truncated_string), MAX_ALLOWED_TEXT_LENGTH)

0 comments on commit d405e06

Please sign in to comment.